QNAM issues
-
I have some really strange issues with networking using QNAM. My application is constantly sending and receiving data from network and after an arbitrary amount of time the manager starts reporting the network as inaccessible. It may happen within an hour or after a day but it does eventually happen without exception. There is no problem with network access (I've been running ping in a command terminal with no packets lost). I'm using Windows 7 for deployment, but if I run the same code on Linux, there are no such issues (which is my main platform for developing)
I'm using just one instance of QNAM per application but if I try to use a few such, they all start reporting network as inaccessible at the same time. If I check for network accessibility and see there is allegedly no access, I create a new QNAM instance, and it will show that network is in fact accessible (which it is). But here things get really nasty. If I try sending a request using the new QNAM instance, the QNetworkReply instance may timeout (I set a timer to check for a timeout period), and when I call abort() on it, the application may crash with a segfault, as if the reply has been destroyed in the interim. But this doesn't happen every time when a new QNAM instance is initialized and used
This purported loss of network access is hard to trace since it happens rarely (it may take a few days of application running). If I try to emulate inaccessibility by setting the QNetworkAccessManager::NotAccessible flag using setNetworkAccessible method, application creates a new QNAM instance as it should but there are no crashes. I stress tested the application for a few hours setting network inaccessible every few seconds, but I still couldn't make it segfault
What could it be?
-
Hi,
Pretty strange indeed. What version of Qt are you using ?
Is your Linux machine on the same network as your Windows machine ?
-
Yes, I'm running Windows 7 as a virtual machine under VmWare and using the latest 5.8.0 version of Qt. I run Linux on the same host and use the same version of Qt. Regarding crashes, I'm now running a test (since yesterday's evening) to check if the abort() method on a QNetworkReply timeout does not get called twice. I'm calling this method from a timerEvent() while the timer associated with this reply is killed in the slot which abort() should call, and which is also connected to finished() signal for processing network replies (I connect QNetworkReply finished() signal to it, not QNAM's). I don't destroy the timer in the timerEvent() function itself since it is destroyed in the slot processing finished() signal which abort() allegedly calls (as per documentation). So if this slot doesn't get called for some reason, then the timer event with that timerId will be called again and thus segfault condition could get raised since the QNetworkReply instance associated with this timerId could already be destroyed. It is explicitly destroyed in the slot connected to finished() signal but if the latter somehow doesn't get called that would lead to double calling the timer event slot, though I'm not sure if calling abort() second time on a live QNetworkReply instance is not allowed
That would probably explain the crashes but not the major issue, i.e. why QNAM stops working after some time
-
A stack trace would be useful to determine that.
-
It kinda looks that I have fixed the crash. Now I explicitly kill all running timers right before I delete the old QNAM instance and create a new one (that I should have done right at the start). So far no crashes (the application is still running). Below is a log of QNAM's resets that my application has done till now:
------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-05 15:55:33.943 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-05 15:59:14.091 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-05 16:04:44.394 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-05 16:50:27.215 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-05 17:23:18.895 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-05 17:55:40.128 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-05 18:00:41.611 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-05 18:12:21.189 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-05 19:17:44.840 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-05 20:02:07.023 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-05 20:14:37.778 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-05 20:54:59.496 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-05 21:09:50.445 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-05 21:25:41.299 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 07:11:01.032 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 07:13:31.352 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 07:16:11.035 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 07:19:31.715 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible)
It seems that the period after which QNAM gets stuck depends on load. I increased the number of packets sent more than 5 times as per usual. setLinks gets called every time finished() signal is emitted, and if the QNAM reports the network as inaccessible, a new QNAM instance is initialized and it shows that the the network is in fact quite accessible (the line which tells QNetworkAccessManager::NetworkAccessibility(Accessible) is from a newly created QNAM instance). Note that QNAM didn't get stuck in the evening and night for almost 10 hours
The code which resets the QNAM looks as follows (NetworkAccessManager class is just a wrapper around QNetworkAccessManager, it inherits directly from QObject):
void NetworkAccessManager::setLinks(QNetworkReply *reply) { if (links->networkAccessible() == QNetworkAccessManager::NotAccessible) { QNetworkAccessManager *fresh = new QNetworkAccessManager(); if (fresh->networkAccessible() == QNetworkAccessManager::Accessible) { qDebug() << "setLinks called - " << links->networkAccessible() << " : " << QDateTime::currentDateTime(); qDebug() << "setLinks called - " << fresh->networkAccessible(); qDebug() << "------------------------"; reply->setParent(fresh); empty(); //there I kill running timers reset(); //some other data structures are reset there delete links; links = fresh; } else delete fresh; } }
links is declared as an external global variable
During the test (it is still running) there was no time when network was inaccessible for real. A network connection error would be reported from the function processing timer events (timerEvent(QTimerEvent *event)) when a QNetworkReply timed out, but there has been none so far (not due to lost network connection). Also, I'm running ping in parallel (only 2 packets got lost out of 87860 sent as of this moment). Therefore, all cases when QNAM networkAccessible() method reports network as inaccessible are bogus
-
Can you by any chance test that on a real Windows machine ? I wonder if there's something from the virtualisation that has any influence in this case.
As for your timer issue, wouldn't it be simpler to have a QTimer single shot that you re-trigger when needed or otherwise just stop ?
-
Actually, I thought about one-shot timers but after I had already done everything with regular ones (I would still have to kill them explicitly after deleting the stuck QNAM instance). I will likely try using them next time when something comes up which would require timers. Regarding a real machine with Windows, I think I can clone a virtual machine to a whole partition and then boot it directly. But there shouldn't be these issues. Whenever I had something not working and said that I ran it in a virtual environment, people were quick on the trigger to claim that it was just because of that. Unsurprisingly, in the end it usually turned out that the problem had nothing to do with running anything in a virtual machine
Anyway, my app is still running (no more crashes), here's the continuation of the log:
------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 10:05:40.288 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 10:59:41.969 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 12:39:47.549 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 12:45:07.433 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 13:31:10.047 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 14:03:21.735 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 14:38:43.685 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 14:49:13.942 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 14:55:44.369 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 15:11:45.380 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 15:17:25.833 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 15:21:25.721 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 15:57:07.703 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 16:00:17.879 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------ setLinks called - QNetworkAccessManager::NetworkAccessibility(NotAccessible) : QDateTime(2017-04-06 16:10:58.425 RTZ 2 (çèìà) Qt::TimeSpec(LocalTime)) setLinks called - QNetworkAccessManager::NetworkAccessibility(Accessible) ------------------------
I think I should post a bug report
-
Don't forget to put all possible details about your network setup that might help to find a reason.