Solved Implementing a timeout with QNetworkAccessManager
-
Hi,
out of curiosity: have you considered using QNetworkRequest::setTransferTimout()? Same method exists for QNetworkAccessManager - I haven't used it but from the looks of - might do the trick? -
@Christian-Ehrlicher There isn't really a GUI in this application - everything runs sequentially on one thread so it's fine if that thread gets blocked. It isn't going to be doing anything until it knows if resourceOk returned true or not. That's why I was using a local event loop in the first place!
-
@artwaw Hello thank you for the suggestion! I was wondering why I didn't implement that - it's Qt 5.15 apparently and I'm in 5.13 and can't upgrade!
I'm guessing they implemented that precisely because of people like me posting questions about how to do this (rather obvious) operation using QTimer
-
@Jez1337 said in Implementing a timeout with QNetworkAccessManager:
I'm guessing they implemented that precisely because of people like me posting questions about how to do this (rather obvious) operation using QTimer
But this is async too.
Again: no local eventloops.
-
@Jez1337 In 5.13 you can have QNetworkError enum and error() signal in QNetworkReply class - you can connect to that. There is no need to break async.
Maybe it is worth to examine how you can manipulate timeout this way? -
@artwaw do you mean when my timer expires, emit
QNetworkReply::error(QNetworkReply::TimeoutError)
, and then use one error handler for everything? I think that would work as a similar alternative to what @Christian-Ehrlicher suggested.Recap
-
Why does removing the event loop cause the code to work, when it should fail? Not sure yet. @SGaist suggested maybe OpenSSL is actually there, but I'm not sure how to check since it's not being found in the command prompt
-
We can remove the event loop entirely. This sidesteps the issue altogether, making the function more event driven. However I'm reluctant for two reasons:
a) I'm using the function as follows:
if (resourceOk("www.google.com")) //Do stuff else //Do other stuff
I can't see any easy way to keep the interface this clean while also having
resourceOk()
use separate event handlers for different signals under the hood.
b) It doesn't matter if my function blocks, because it's not called at times where there is also a human user there mucking around in a GUINext steps:
- If there is a way to keep using
resourceOk()
as above while using separate signals and slots under the hood, then I'll go ahead and remove the event loop - I'm going to try a search of the C drive for the dlls included in OpenSSL, to rule out the possibility that it is hiding in there somewhere and my code is actually working properly. If anybody knows a faster way of finding if OpenSSL was installed, please do say!
-
-
Experimenting with various different computers and verisons of the code have revealed the answers:
Solution
Why does removing the event loop cause the code to work, when it should fail? Because my function never waits for the reply to finish before trying to handle the response. When the event loop is removed, the function jumps straight to handling the resonse, and apparently
QNetworkReply::error()
returnsNoError
by default, until such a time as it knows an error has occured. This makes it look like OpenSSL is working, when in fact it isn't even present on the system.In hindsight, this is obvious when you look at the code without the event loop:
std::unique_ptr<QNetworkAccessManager> networkManager; QNetworkRequest request; request.setUrl(url); QNetworkReply* reply = networkManager->get(request); switch (reply->error()) { //Response handling here }
Miscellanea discovered while doing this
-
Many Qt Windows developers use the Shining Light version of OpenSSL. This installs a lot of stuff but all that seems to matter from there in terms of getting QNetworkAccessManager to work is to have libcrypto-1_1-x64.dll and libssl-1_1-x64.dll in one of the folders referenced by the PATH environment variable, as well as a certificates file pointed to by the SSL_CERT_FILE environment variable
-
When you uninstall the Shining Light setup of OpenSSL, it can leave its .dlls in your C:\Windows\System32 folder, making it look like it has been uninstalled when it is, in fact, still there
-
My local event loop is considered bad practice because it blocks the thread it is running in, but actually there was absolutely nothing wrong with my function. In my application which doesn't have any user interactivity, blocking the thread is a nonissue because nothing else is going on at the same time. More modern users of Qt can do away with
QTimer
entirely and use QNetworkRequest::setTransferTimout(), as pointed out by @artwaw
Thanks to everyone for their help, which undoubtedly allowed me to pin down the problem
-
-
@Jez1337 said in Implementing a timeout with QNetworkAccessManager:
When you uninstall the Shining Light setup of OpenSSL, it can leave its .dlls in your C:\Windows\System32 folder, making it look like it has been uninstalled when it is, in fact, still there
Are you sure their installer put the dlls in the system folder ? If so this is wrong and they should be notified about that issue.
-
@Jez1337 said in Implementing a timeout with QNetworkAccessManager:
-
Many Qt Windows developers use the Shining Light version of OpenSSL. This installs a lot of stuff but all that seems to matter from there in terms of getting QNetworkAccessManager to work is to have libcrypto-1_1-x64.dll and libssl-1_1-x64.dll in one of the folders referenced by the PATH environment variable, as well as a certificates file pointed to by the SSL_CERT_FILE environment variable
-
When you uninstall the Shining Light setup of OpenSSL, it can leave its .dlls in your C:\Windows\System32 folder, making it look like it has been uninstalled when it is, in fact, still there
The current 64-bit MSI installer by Shining Light (Win64OpenSSL_Light-1_1_1i.msi) installs the DLLs into C:\Program Files\OpenSSL-Win64. As @SGaist said, no installer (aside from official Windows installers) should put anything into C:\Windows
Anyway, you can install OpenSSL directly from the Qt online installer nowadays.
-
-
@JKSH , @SGaist You're both correct that the Shining Light installer doesn't put anything in C:\Windows\System32, unless you explicitly tell it to by checking the option during the installation process to do exactly that!
I avoid using the Qt online installer where possible but I think it was a good idea for them to include it so thank you for pointing that out. Having to install OpenSSL separately was always a faff, especially when an OpenSSL stack is included in the Chromium browser engine anyway
-
@Jez1337 said in Implementing a timeout with QNetworkAccessManager:
the Shining Light installer doesn't put anything in C:\Windows\System32, unless you explicitly tell it to by checking the option during the installation process to do exactly that!
Yikes, that's a dangerous option!
I also wonder what happens if you install the 64-bit OpenSSL DLLs there, and then you run a 32-bit app that needs it...
Having to install OpenSSL separately was always a faff, especially when an OpenSSL stack is included in the Chromium browser engine anyway
To avoid DLL Hell, it's often worth keeping app-specific copies of DLLs, even if it means having some duplicates on the same machine.