diff options
-rw-r--r-- | src/network/access/qnetworkaccesshttpbackend.cpp | 6 | ||||
-rw-r--r-- | src/s60main/newallocator_hook.cpp | 40 | ||||
-rw-r--r-- | tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 44 |
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() { |