summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authormread <qt-info@nokia.com>2011-11-18 16:21:07 (GMT)
committermread <qt-info@nokia.com>2011-11-21 09:18:00 (GMT)
commitbd5dfa8fd2f4d5dc4a1fe0984a53b966cff6470f (patch)
tree76f1e7ef0a0a164d2d1d0dc289a0982ea0547b66 /src/corelib
parent52a93f068d2869fbe4e4deae2ed704d683e12834 (diff)
downloadQt-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.cpp13
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian.cpp27
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian_p.h4
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