Nominate our 2022 Qt Champions!

QSocketNotifier Exception After Deletion of QNetworkAccessManager Object

  • Hello,

    I have a class which handles network operations. It own a QNetworkAccessManager pointer which it uses for network requests/replies. Occasionally I experience network loss, when this occurs to reset the QNAM I simply delete it and create a new one as suggested on these threads: Here & Here

    delete m_mgr;
    m_mgr = new QNetworkAccessManager(m_parent);
    // connect to finish done on each QNetworkReply object
    connect(m_mgr, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)), this, SLOT(sslErrors(QNetworkReply*, const QList<QSslError>&)));

    The issue is that occasionally after this it seems like the original QNAM object is still being acted upon by QT behind the curtains. The reason I believe this is because the application will crash with the exception "QSocketNotifier: Invalid socket 12 and type 'Read', disabling..." soon after the next m_mgr->get() call.

    Before I delete the QNAM I call close() or abort() on all exisiting QNetworkReply's (based on what isFinished returns). I've tried replacing the the actual deletion with m_mgr->deleteLater();. I've tried making m_mgr a shared_ptr. I've tried disconnecting all signals from m_mgr with m_mgr->disconnect(). Nothing seems to fix this issue though.

    What am I doing wrong? Do I need to delete the QNAM object then wait for it's finished() signal and call deleteLater() in that slot?

    EDIT: QT Version 4.8.7

  • Lifetime Qt Champion

    Hi and welcome to devnet,

    You should rather use deleteLater, this will allow pending events to be processed before deleting the object.

  • Hey SGaist, thanks for the reply. I have tried using deleteLater and it does not seem to fix the issue. Would I need to wait for QNAM's finished() signal or something before I reset the pointer?

  • Lifetime Qt Champion

    4.8.7 ? What OS are you running that on ?

    The pointer doesn't care about what is happening the old instance, you are just replacing an address. The deletion will happen at the next possible time.

    What kind of pointer is m_mgr ? A classic raw pointer ?

    Do you have a stack trace of the crash you are experiencing ?

  • Yep, 4.8.7. Running on a linux build created with Yocto 2.2, arch armv7-a, kernel 4.8. I've tried m_mgr as both a raw pointer and a std::shared_ptr. I do not have a stack trace, I'm probably going to attempt to grab one now.

  • Lifetime Qt Champion

    By the way, are you locked on Qt 4 ? I has reached end of life so if you are starting a new project, you might want to consider moving to Qt 5.

  • Yeah unfortunately I'm stuck on Qt 4. This is (hopefully) the last bug fix on a 2-3 year old project.

  • So I obtained the stack trace but it doesn't really help me as I don't know exactly what I'm looking for. I can see PID 567 is what is throwing the exception and it looks like it's due to a write or read of fd=3, but other than that I'm not really sure.

    Stack Trace

  • Lifetime Qt Champion

    This is not a stack trace from the debugger but a strace output - this won't help us.
    And why do you recreate the QNetworkAccessManager at all? There is no reason for it.

  • Ahh sorry I thought an strace would help. It might take me a bit to get an actual stack trace as I'd have to set up my build environment with debugging symbols.

    The reason I was recreating QNetworkAccessManager is because I was under the impression that I needed to do so when I lost network access (m_mgr->networkAccessible() != QNetworkAccessManager::Accessible). That's what a user said on this stack overflow post. Is that incorrect? If I could just used something like setNetworkAccessible() that would avoid this whole mess. I've tested out removing the QNAM deletion and the exception does not occur.

    I guess I am sort of confused in general about what QNetworkAccessManager::NetworkAccessibility even represents? It's not going to alter the actual network state, NetworkManager handles that