summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/access/qnetworkaccesshttpbackend.cpp6
-rw-r--r--src/s60main/newallocator_hook.cpp40
-rw-r--r--tests/auto/qnetworkreply/tst_qnetworkreply.cpp44
3 files changed, 76 insertions, 14 deletions
diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp
index aa477fb..42dc33d 100644
--- a/src/network/access/qnetworkaccesshttpbackend.cpp
+++ b/src/network/access/qnetworkaccesshttpbackend.cpp
@@ -721,6 +721,12 @@ void QNetworkAccessHttpBackend::readFromHttp()
if (!httpReply)
return;
+ if (!http) {
+ // Connection has been destroyed
+ finished();
+ return;
+ }
+
// We read possibly more than nextDownstreamBlockSize(), but
// this is not a critical thing since it is already in the
// memory anyway
diff --git a/src/s60main/newallocator_hook.cpp b/src/s60main/newallocator_hook.cpp
index 7e0b344..4cec214 100644
--- a/src/s60main/newallocator_hook.cpp
+++ b/src/s60main/newallocator_hook.cpp
@@ -109,26 +109,38 @@ struct SStdEpocThreadCreateInfo : public SThreadCreateInfo
* startup. On return, there is some kind of heap allocator installed on the
* thread.
*/
+typedef int (*TSetupThreadHeapFunc)(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo);
+// keep the SetupThreadHeap() pointer so that we don't reload QtCore.dll after the first time
+static TSetupThreadHeapFunc gp_qt_symbian_SetupThreadHeap = 0;
+static bool gp_qt_symbian_SetupThreadHeap_set = false;
+
TInt UserHeap::SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo)
{
TInt r = KErrNone;
#ifndef __WINS__
- // attempt to create the fast allocator through a known export ordinal in qtcore.dll
- RLibrary qtcore;
- if (qtcore.Load(QtCoreLibName) == KErrNone)
- {
- const int qt_symbian_SetupThreadHeap_eabi_ordinal = 3713;
- TLibraryFunction libFunc = qtcore.Lookup(qt_symbian_SetupThreadHeap_eabi_ordinal);
- if (libFunc)
- {
- typedef int (*TSetupThreadHeapFunc)(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo);
- TSetupThreadHeapFunc p_qt_symbian_SetupThreadHeap = TSetupThreadHeapFunc(libFunc);
- r = (*p_qt_symbian_SetupThreadHeap)(aNotFirst, aInfo);
+ // on first call, aNotFirst will be false.
+ // on second call, gp_qt_symbian_SetupThreadHeap_set will be false(!) because WSD is zeroed after the first call
+ // on subsequent calls, both will be true and we can use the stored SetupThreadHeap() pointer
+ if (aNotFirst && gp_qt_symbian_SetupThreadHeap_set) {
+ if (gp_qt_symbian_SetupThreadHeap)
+ return (*gp_qt_symbian_SetupThreadHeap)(aNotFirst, aInfo);
+ } else {
+ // attempt to create the fast allocator through a known export ordinal in qtcore.dll
+ RLibrary qtcore;
+ gp_qt_symbian_SetupThreadHeap_set = true;
+ if (qtcore.Load(QtCoreLibName) == KErrNone) {
+ const int qt_symbian_SetupThreadHeap_eabi_ordinal = 3713;
+ TLibraryFunction libFunc = qtcore.Lookup(qt_symbian_SetupThreadHeap_eabi_ordinal);
+ if (libFunc) {
+ TSetupThreadHeapFunc p_qt_symbian_SetupThreadHeap = TSetupThreadHeapFunc(libFunc);
+ gp_qt_symbian_SetupThreadHeap = p_qt_symbian_SetupThreadHeap;
+ r = (*p_qt_symbian_SetupThreadHeap)(aNotFirst, aInfo);
+ }
+ qtcore.Close();
+ if (libFunc)
+ return r;
}
- qtcore.Close();
- if (libFunc)
- return r;
}
#endif
diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
index 28832b2..d4e388d 100644
--- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
@@ -317,6 +317,8 @@ private Q_SLOTS:
void getAndThenDeleteObject_data();
void getAndThenDeleteObject();
+ void deleteManagerWhileGetIsInProgress();
+
void symbianOpenCDataUrlCrash();
void qtbug12908compressedHttpReply();
@@ -5109,6 +5111,48 @@ void tst_QNetworkReply::getAndThenDeleteObject()
}
}
+void tst_QNetworkReply::deleteManagerWhileGetIsInProgress()
+{
+ // yes, this will leak if the testcase fails. I don't care. It must not fail then :P
+ QNetworkAccessManager *manager = new QNetworkAccessManager();
+ QNetworkRequest request("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile");
+ QNetworkReply *reply = manager->get(request);
+ reply->setReadBufferSize(1024);
+
+ // Reset reply's parent to allow it to outlive the manager
+ reply->setParent(0);
+
+ // Wait until a buffer is received
+ int totalWait = 0;
+ while (!reply->bytesAvailable()) {
+ QTest::qWait(20);
+ totalWait += 20;
+ QVERIFY( totalWait <= 5*1000);
+ }
+
+ QVERIFY(reply->bytesAvailable());
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
+ QVERIFY(!reply->isFinished()); // must not be finished
+
+ // Read the data to request next buffer's worth from the server
+ (void)reply->readAll();
+
+ QSignalSpy replyFinishedSpy(reply, SIGNAL(finished()));
+
+ // Delete the manager
+ delete manager;
+ manager = 0;
+
+ // Wait to allow reply to process any pending events
+ QTest::qWait(100);
+
+ // The reply should be finished
+ QVERIFY(reply->isFinished());
+ QCOMPARE(replyFinishedSpy.count(), 1);
+
+ delete reply;
+}
+
// see https://bugs.webkit.org/show_bug.cgi?id=38935
void tst_QNetworkReply::symbianOpenCDataUrlCrash()
{