"CoInitialize has not been called." warning
-
After migrating from Qt 5.13.2 to 5.14.0, our unit tests suddenly started spitting out the following warning:
qt.network.monitor: Failed to subscribe to network connectivity events: "CoInitialize has not been called." qt.network.monitor: failed to start network status monitoring
The moment this happens, the top of the call stack is as follows:
Qt5Networkd.dll!QNetworkListManagerEvents::start() Line 594 C++ Qt5Networkd.dll!QNetworkStatusMonitorPrivate::start() Line 652 C++ Qt5Networkd.dll!QNetworkStatusMonitor::start() Line 677 C++ Qt5Networkd.dll!QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest & originalReq, QIODevice * outgoingData) Line 1479 C++ Qt5Networkd.dll!QNetworkAccessManager::post(const QNetworkRequest & request, QIODevice * data) Line 893 C++ Qt5Networkd.dll!QNetworkAccessManager::post(const QNetworkRequest & request, QHttpMultiPart * multiPart) Line 930 C++ OurOwn.dll!OurOwnClass::someMethod(...)
so this happens when we call
QNetworkAccessManager::post
from inside OurOwnClass::someMethod().Any ideas on what has changed between 5.13.2 and 5.14.0 that triggers this warning, and on how to fix it, are welcome!
-
@manordheim said in "CoInitialize has not been called." warning:
@Bart_Vandewoestyne Yeah, this specific bug was fixed in 5.15.1.
Is there an official bug report for that specific bug? I've searched https://bugreports.qt.io/ but cannot find it :-( Would be nice to know what commit(s) fix(es) it, so we can apply a patch to our local 5.15.0 vendor branch.
@Bart_Vandewoestyne said in "CoInitialize has not been called." warning:
Is there an official bug report for that specific bug? I've searched https://bugreports.qt.io/ but cannot find it :-( Would be nice to know what commit(s) fix(es) it, so we can apply a patch to our local 5.15.0 vendor branch.
Bugreport: https://bugreports.qt.io/browse/QTBUG-84031
Patch: https://codereview.qt-project.org/c/qt/qtbase/+/305169Thanks to @manordheim !
I consider this issue fixed. All I must do is wait for 5.15.1 and test again :-) -
It seems that there are some new internal classes which use COM APIs in Windows.
Have you ever moved QNetworkAccessManager to another thread?
I think this is probably the reason becauseCoInitialize
needs to be called in every thread calling COM APIs. -
I did come across https://bugreports.qt.io/browse/QTBUG-84031 in my search, and the commit that fixes it: https://github.com/qt/qtbase/commit/f1f0aa4a3a7d364b5110122a8f77079a7742c4e9
Apparently, this fix will be included in Qt 5.15.1 (to be released in August 2020), so I'll definitely try with that version to see if the warning goes away.In the meanwhile, I'll double-check our code tomorrow to see if we are moving a
QNetworkAccessManager
object to another thread somewhere. -
Hello! With 5.14.0 the QNetworkStatusMonitor was added. Without knowing more (and assuming it was not moved across threads); was QNetworkAccessManager::post called from a different thread than it was created in? Otherwise I'm not sure what would cause it from looking at the stacktrace and the code. But if that's the case then that's not really supported: Since QNetworkAccessManager is based on QObject, it can only be used from the thread it belongs to.
-
It seems that there are some new internal classes which use COM APIs in Windows.
Have you ever moved QNetworkAccessManager to another thread?
I think this is probably the reason becauseCoInitialize
needs to be called in every thread calling COM APIs.@Bonnie Yes, apparently, there is one place in our code where the
QNetworkAccessManager
object is moved to another thread. However, to the best of my knowledge, we are only using ourQNetworkAccessManager
object in the thread it belongs to.You write that
CoInitialize
needs to be called in every thread calling COM APIs... Do you have any idea how we can make sure that this is the case after moving ourQNetworkAccessManager
object to a different thread? -
@Bonnie Yes, apparently, there is one place in our code where the
QNetworkAccessManager
object is moved to another thread. However, to the best of my knowledge, we are only using ourQNetworkAccessManager
object in the thread it belongs to.You write that
CoInitialize
needs to be called in every thread calling COM APIs... Do you have any idea how we can make sure that this is the case after moving ourQNetworkAccessManager
object to a different thread?@Bart_Vandewoestyne
You could call the necessaryCoInitialize()
immediately before/after moving yourQNetworkAccessManager
object to a different thread (call from the destination thread)? -
@manordheim, I am still fighting with this issue, but probably getting closer to nailing it down. Here's the situation: we have some kind of wrapper class, let's call it
Wrapper
, that has a member of typeQNetworkAccessManager
and ofQThread
:class Wrapper :: public QObject { ... private: QNetworkAccessManager mvNetworkAccessManager; QThread mvThread; }
Inside
Wrapper
's constructor, we movemvNetworkAccessManager
to another thread that we then start:Wrapper::Wrapper() : mvNetworkAccessManager(this) { ... some logging with QThread::currentThreadId() to print the thread ID ... this->moveToThread(&mvThread); mvThread.start(); }
The
QNetworkAccessManager::post
method gets called from a member function of theWrapper
class:void Wrapper::doThePost() { ... ... some logging with QThread::currentThreadId() to print the thread ID ... reply = mvNetworkAccessManager.post(... stuff ...) ... }
The
currentThreadId()
that gets printed from the constructor is different from thecurrentThreadId()
that gets printed fromdoThePost()
. Am I right if I say that this is the problem?To be able to call
CoInitializeEx
from the thread where thepost()
method is called, I changed the constructor code as follows:this->moveToThread(&mvThread); connect(&mvThread, &QThread::started, this, &Wrapper::mpHandleThreadStarted); connect(&mvThread, &QThread::finished, this, &Wrapper::mpHandleThreadFinished); mvThread.start();
with
void ICNetworkAccessManager::mpHandleThreadStarted() { ... some logging with QThread::currentThreadId() to print the thread ID ... HRESULT hr; hr = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hr)) { ... print failure ... } else { ... print success ... } }
and
void ICNetworkAccessManager::mpHandleThreadFinished() { ... some logging with QThread::currentThreadId() to print the thread ID ... CoUninitialize(); }
From the logging in the
mpHandleThreadStarted
method, I can see that I am callingCoInitializeEx
from the same thread as the one where I call myQNetworkAccessManager::post
. I also don't see the "CoInitialize has not been called " warning anymore, but unfortunately, the new warning (occurring at exactly the same location, when callingpost()
) is nowqt.network.monitor: Failed to subscribe to network connectivity events: "The application called an interface that was marshalled for a different thread."
Before that warning, I also see
onecore\com\combase\dcomrem\stdid.cxx(725)\combase.dll!754896A6: (caller: 754B13B1) ReturnHr(1) tid(4490) 8001010E The application called an interface that was marshalled for a different thread. onecore\com\combase\dcomrem\stdid.cxx(725)\combase.dll!754896A6: (caller: 754B13B1) ReturnHr(2) tid(4490) 8001010E The application called an interface that was marshalled for a different thread. onecore\com\combase\dcomrem\stdid.cxx(725)\combase.dll!754896A6: (caller: 754B13B1) ReturnHr(3) tid(4490) 8001010E The application called an interface that was marshalled for a different thread. onecore\com\combase\dcomrem\stdid.cxx(725)\combase.dll!754896A6: (caller: 754B13B1) ReturnHr(4) tid(4490) 8001010E The application called an interface that was marshalled for a different thread.
and so this is again where I'm stuck. Any ideas/suggestions on how to proceed are very welcome!
-
Hello! With 5.14.0 the QNetworkStatusMonitor was added. Without knowing more (and assuming it was not moved across threads); was QNetworkAccessManager::post called from a different thread than it was created in? Otherwise I'm not sure what would cause it from looking at the stacktrace and the code. But if that's the case then that's not really supported: Since QNetworkAccessManager is based on QObject, it can only be used from the thread it belongs to.
@manordheim said in "CoInitialize has not been called." warning:
[...] But if that's the case then that's not really supported: Since QNetworkAccessManager is based on QObject, it can only be used from the thread it belongs to.
Just to make sure I understand the Qt documentation right: what exactly do they mean by "it can only be used from the thread it belongs to". Do they mean "the thread it was created" or "the thread it was moved to"? I assume the second, but just need confirmation ;-)
-
@manordheim said in "CoInitialize has not been called." warning:
[...] But if that's the case then that's not really supported: Since QNetworkAccessManager is based on QObject, it can only be used from the thread it belongs to.
Just to make sure I understand the Qt documentation right: what exactly do they mean by "it can only be used from the thread it belongs to". Do they mean "the thread it was created" or "the thread it was moved to"? I assume the second, but just need confirmation ;-)
@Bart_Vandewoestyne said in "CoInitialize has not been called." warning:
"the thread it was created" or "the thread it was moved to"?
both
-
@Bart_Vandewoestyne said in "CoInitialize has not been called." warning:
"the thread it was created" or "the thread it was moved to"?
both
@jsulm said in "CoInitialize has not been called." warning:
both
I'm afraid I cannot follow here... This is my understanding: if the object is created in thread A, and is not moved yet to a thread B, then it 'belongs to' thread A and all its slots will run on thread A. Once we move the object to thread B (using moveToThread), then it 'belongs to' thread B and from that moment on all its slots will run on thread B (if I understand things correctly, please correct me if I'm wrong).
Is that why you replied 'both'? Or am I fundamentally misunderstanding something here?
-
Using Qt 5.15.0, I was able to create the following minimal example that reproduces the problem:
QNetworkRequest request; QHttpMultiPart* multiPart = new QHttpMultiPart(); QNetworkAccessManager mgr; QThread thread; QObject::connect( &thread, &QThread::started, [&]() { mgr.post(request, multiPart); } ); mgr.moveToThread(&thread); thread.start(); thread.quit(); thread.wait();
and thus triggers the warning
qt.network.monitor: Failed to subscribe to network connectivity events: "CoInitialize has not been called." qt.network.monitor: failed to start network status monitoring
I think my two questions are now:
- Is this a bug in Qt? Shouldn't the internal network monitoring code call CoInitialize at the right place?
- If it is not a bug, then how to make the warning go away?
-
Using Qt 5.15.0, I was able to create the following minimal example that reproduces the problem:
QNetworkRequest request; QHttpMultiPart* multiPart = new QHttpMultiPart(); QNetworkAccessManager mgr; QThread thread; QObject::connect( &thread, &QThread::started, [&]() { mgr.post(request, multiPart); } ); mgr.moveToThread(&thread); thread.start(); thread.quit(); thread.wait();
and thus triggers the warning
qt.network.monitor: Failed to subscribe to network connectivity events: "CoInitialize has not been called." qt.network.monitor: failed to start network status monitoring
I think my two questions are now:
- Is this a bug in Qt? Shouldn't the internal network monitoring code call CoInitialize at the right place?
- If it is not a bug, then how to make the warning go away?
@Bart_Vandewoestyne said in "CoInitialize has not been called." warning:
Is this a bug in Qt? Shouldn't the internal network monitoring code call CoInitialize at the right place?
I think it is.
And we all know there will be a fix in 5.15.1, don't we?
Unfortunately it seems to be delayed.
Just hope it could be released ASAP... -
Using Qt 5.15.0, I was able to create the following minimal example that reproduces the problem:
QNetworkRequest request; QHttpMultiPart* multiPart = new QHttpMultiPart(); QNetworkAccessManager mgr; QThread thread; QObject::connect( &thread, &QThread::started, [&]() { mgr.post(request, multiPart); } ); mgr.moveToThread(&thread); thread.start(); thread.quit(); thread.wait();
and thus triggers the warning
qt.network.monitor: Failed to subscribe to network connectivity events: "CoInitialize has not been called." qt.network.monitor: failed to start network status monitoring
I think my two questions are now:
- Is this a bug in Qt? Shouldn't the internal network monitoring code call CoInitialize at the right place?
- If it is not a bug, then how to make the warning go away?
@Bart_Vandewoestyne Yeah, this specific bug was fixed in 5.15.1. But more recently the built-in connection status pre-check was dropped entirely from 5.15.1 (and 6.0).
-
@Bart_Vandewoestyne Yeah, this specific bug was fixed in 5.15.1. But more recently the built-in connection status pre-check was dropped entirely from 5.15.1 (and 6.0).
@manordheim said in "CoInitialize has not been called." warning:
@Bart_Vandewoestyne Yeah, this specific bug was fixed in 5.15.1.
Is there an official bug report for that specific bug? I've searched https://bugreports.qt.io/ but cannot find it :-( Would be nice to know what commit(s) fix(es) it, so we can apply a patch to our local 5.15.0 vendor branch.
-
@manordheim said in "CoInitialize has not been called." warning:
@Bart_Vandewoestyne Yeah, this specific bug was fixed in 5.15.1.
Is there an official bug report for that specific bug? I've searched https://bugreports.qt.io/ but cannot find it :-( Would be nice to know what commit(s) fix(es) it, so we can apply a patch to our local 5.15.0 vendor branch.
@Bart_Vandewoestyne said in "CoInitialize has not been called." warning:
Is there an official bug report for that specific bug? I've searched https://bugreports.qt.io/ but cannot find it :-( Would be nice to know what commit(s) fix(es) it, so we can apply a patch to our local 5.15.0 vendor branch.
Bugreport: https://bugreports.qt.io/browse/QTBUG-84031
Patch: https://codereview.qt-project.org/c/qt/qtbase/+/305169Thanks to @manordheim !
I consider this issue fixed. All I must do is wait for 5.15.1 and test again :-) -
@Bart_Vandewoestyne said in "CoInitialize has not been called." warning:
Is there an official bug report for that specific bug? I've searched https://bugreports.qt.io/ but cannot find it :-( Would be nice to know what commit(s) fix(es) it, so we can apply a patch to our local 5.15.0 vendor branch.
Bugreport: https://bugreports.qt.io/browse/QTBUG-84031
Patch: https://codereview.qt-project.org/c/qt/qtbase/+/305169Thanks to @manordheim !
I consider this issue fixed. All I must do is wait for 5.15.1 and test again :-)@Bart_Vandewoestyne said in "CoInitialize has not been called." warning:
[...] All I must do is wait for 5.15.1 and test again :-)
For the record: Qt 5.15.1 is available from http://download.qt.io/official_releases/qt/5.15/5.15.1/.
I tested again using this version, and theqt.network.monitor
warnings no longer appear, so problem solved.Thanks!