diff options
author | mread <qt-info@nokia.com> | 2011-11-18 16:21:07 (GMT) |
---|---|---|
committer | mread <qt-info@nokia.com> | 2011-11-21 09:18:00 (GMT) |
commit | bd5dfa8fd2f4d5dc4a1fe0984a53b966cff6470f (patch) | |
tree | 76f1e7ef0a0a164d2d1d0dc289a0982ea0547b66 /src/corelib | |
parent | 52a93f068d2869fbe4e4deae2ed704d683e12834 (diff) | |
download | Qt-bd5dfa8fd2f4d5dc4a1fe0984a53b966cff6470f.zip Qt-bd5dfa8fd2f4d5dc4a1fe0984a53b966cff6470f.tar.gz Qt-bd5dfa8fd2f4d5dc4a1fe0984a53b966cff6470f.tar.bz2 |
Surviving out of memory in Qt Quick app
The QtQuickPlayground app contains a version of samegame which allow
the user to edit the code. By setting the ball size to 8, the app can
run out of memory. This leaves it in a pretty bad state. But apps
on Symbian shouldn't crash due to OOM and should allow some operation.
This change fixes the immediate OOM crashes in declarative, gui and
corelib. It shows warning dialogs which explain what has gone wrong and
leaves the app in a state that can be exited cleanly
from the Symbian task list.
Task-number: QT-5319
Reviewed-by: Shane Kearns
Reviewed-by: Gareth Stockwell
Reviewed-by: Martin Jones
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/global/qglobal.cpp | 13 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_symbian.cpp | 27 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_symbian_p.h | 4 |
3 files changed, 30 insertions, 14 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 84d68e5..3675fc7 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2207,16 +2207,13 @@ void qt_message_output(QtMsgType msgType, const char *buf) OutputDebugString(reinterpret_cast<const wchar_t *> (fstr.utf16())); #elif defined(Q_OS_SYMBIAN) // RDebug::Print has a cap of 256 characters so break it up - _LIT(format, "[Qt Message] %S"); - const int maxBlockSize = 256 - ((const TDesC &)format).Length(); + char format[] = "[Qt Message] %S"; + const int maxBlockSize = 256 - sizeof(format); const TPtrC8 ptr(reinterpret_cast<const TUint8*>(buf)); - HBufC* hbuffer = HBufC::New(qMin(maxBlockSize, ptr.Length())); - Q_CHECK_PTR(hbuffer); - for (int i = 0; i < ptr.Length(); i += hbuffer->Length()) { - hbuffer->Des().Copy(ptr.Mid(i, qMin(maxBlockSize, ptr.Length()-i))); - RDebug::Print(format, hbuffer); + for (int i = 0; i < ptr.Length(); i += maxBlockSize) { + TPtrC8 part(ptr.Mid(i, qMin(maxBlockSize, ptr.Length()-i))); + RDebug::Printf(format, &part); } - delete hbuffer; #else fprintf(stderr, "%s\n", buf); fflush(stderr); diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index ea466f5..da6f021 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -749,7 +749,7 @@ public: ObjectRun, ObjectDelayed }; - static RunResult RunMarkedIfReady(TInt &runPriority, TInt minimumPriority); + static RunResult RunMarkedIfReady(TInt &runPriority, TInt minimumPriority, QEventDispatcherSymbian *dispatcher); static bool UseRRActiveScheduler(); private: @@ -808,7 +808,7 @@ void QtRRActiveScheduler::MarkReadyToRun() } } -QtRRActiveScheduler::RunResult QtRRActiveScheduler::RunMarkedIfReady(TInt &runPriority, TInt minimumPriority) +QtRRActiveScheduler::RunResult QtRRActiveScheduler::RunMarkedIfReady(TInt &runPriority, TInt minimumPriority, QEventDispatcherSymbian *dispatcher) { RunResult result = NothingFound; TInt error=KErrNone; @@ -824,12 +824,12 @@ QtRRActiveScheduler::RunResult QtRRActiveScheduler::RunMarkedIfReady(TInt &runPr runPriority = active->Priority(); dataAccess->iStatus.iFlags&=~TRequestStatusAccess::ERequestActiveFlags; int vptr = *(int*)active; // vptr can be used to identify type when debugging leaves - TRAP(error, active->RunL()); + TRAP(error, QT_TRYCATCH_ERROR(error, active->RunL())); if (error!=KErrNone) error=active->RunError(error); if (error) { qWarning("Active object (ptr=0x%08x, vptr=0x%08x) leave: %i\n", active, vptr, error); - pS->Error(error); + dispatcher->activeObjectError(error); } return ObjectRun; } @@ -966,13 +966,15 @@ QEventDispatcherSymbian::QEventDispatcherSymbian(QObject *parent) m_wakeUpDone(0), m_iterationCount(0), m_insideTimerEvent(false), - m_noSocketEvents(false) + m_noSocketEvents(false), + m_oomErrorCount(0) { #ifdef QT_SYMBIAN_PRIORITY_DROP m_delay = baseDelay; m_avgEventTime = 0; idleDetectorThread(); #endif + m_oomErrorTimer.start(); } QEventDispatcherSymbian::~QEventDispatcherSymbian() @@ -1098,7 +1100,7 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla // Standard or above priority AOs are scheduled round robin. // Lower priority AOs can only run if nothing higher priority has run. int runPriority = minPriority; - handledSymbianEvent = QtRRActiveScheduler::RunMarkedIfReady(runPriority, minPriority); + handledSymbianEvent = QtRRActiveScheduler::RunMarkedIfReady(runPriority, minPriority, this); minPriority = qMin(runPriority, int(CActive::EPriorityStandard)); } else { TInt error; @@ -1396,6 +1398,19 @@ QList<QEventDispatcherSymbian::TimerInfo> QEventDispatcherSymbian::registeredTim return list; } +void QEventDispatcherSymbian::activeObjectError(int error) +{ + if (error == KErrNoMemory) { + // limit the number of reported out of memory errors, as the disappearance of the warning + // dialog can trigger further OOM errors causing a loop. + if (m_oomErrorTimer.restart() > 60000) // 1 minute + m_oomErrorCount = 0; + if (m_oomErrorCount++ >= 5) + return; + } + CActiveScheduler::Current()->Error(error); +} + /* * This active scheduler class implements a simple report and continue policy, for Symbian OS leaves * or exceptions from Qt that fall back to the scheduler. diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h index 01f5ab1..869fe31 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian_p.h +++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h @@ -264,6 +264,8 @@ public: static void RequestComplete(TRequestStatus *&status, TInt reason); static void RequestComplete(RThread &threadHandle, TRequestStatus *&status, TInt reason); + void activeObjectError(int error); + private: bool sendPostedEvents(); bool sendDeferredSocketEvents(); @@ -294,6 +296,8 @@ private: int m_delay; int m_avgEventTime; QElapsedTimer m_lastIdleRequestTimer; + int m_oomErrorCount; + QElapsedTimer m_oomErrorTimer; }; #ifdef QT_DEBUG |