Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QNetworkAccessManager post method freezes the calling thread when internet access is down

QNetworkAccessManager post method freezes the calling thread when internet access is down

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 4 Posters 1.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    jojopirato
    wrote on last edited by jojopirato
    #1

    Hi!

    Please consider the following scenario on WIndows 10 x64 and Qt 5.12.4:
    Use a computer with an ethernet connection with internet access with this setup:
    PC - ethernet cable 1- ethernet switch - ethernet cable 2 - internet gateway
    Now Windows will not immediately detect that the ethernet interface is down when we unplug ethernet cable 2.

    Now make sure you have internet access, unplug ethernet cable 2, make a post request with QNetworkAccessManager from the gui thread. the gui thread freezes for 10-20 seconds until post returns.

    I have compiled this in debug mode and interrupted the process, here is the call stack:

    Note that nplugging ethernet cable 1 instead of ethernet cable 2 won't freeze the thread (as the ethernet interface will be down I guess.)

    1  NtWaitForSingleObject                          ntdll                          0x7ffd67fcaa24 
    2  WaitForSingleObjectEx                          KERNELBASE                     0x7ffd64339252 
    3  QMutexPrivate::wait                            qmutex_win.cpp            64   0x7ffd1335bf5c 
    4  QBasicMutex::lockInternal                      qmutex.cpp                573  0x7ffd1335b8c4 
    5  QBasicMutex::lockInternal                      qmutex.cpp                490  0x7ffd1335b658 
    6  QBasicMutex::lock                              qmutex.h                  80   0x7ffd13320184 
    7  QRecursiveMutexPrivate::lock                   qmutex.cpp                707  0x7ffd1335d69f 
    8  QMutex::lock                                   qmutex.cpp                226  0x7ffd1335bd51 
    9  QMutexLocker::QMutexLocker                     qmutex.h                  207  0x7ffd1331a48d 
    10 QSslSocketPrivate::ensureLibraryLoaded         qsslsocket_openssl11.cpp  90   0x7ffd168cdbf1 
    11 QSslSocketPrivate::supportsSsl                 qsslsocket_openssl.cpp    497  0x7ffd168b7f79 
    12 QSslSocketPrivate::ensureInitialized           qsslsocket_openssl.cpp    509  0x7ffd168b7fe9 
    13 QSslConfigurationPrivate::defaultConfiguration qsslsocket.cpp            2280 0x7ffd168980fe 
    14 QSslConfiguration::defaultConfiguration        qsslconfiguration.cpp     1023 0x7ffd16887233 
    15 QNetworkRequest::sslConfiguration              qnetworkrequest.cpp       675  0x7ffd1671eccb 
    16 QNetworkReplyHttpImpl::QNetworkReplyHttpImpl   qnetworkreplyhttpimpl.cpp 193  0x7ffd167d04ae 
    17 QNetworkAccessManager::createRequest           qnetworkaccessmanager.cpp 1480 0x7ffd166f5f72 
    18 QNetworkAccessManager::post                    qnetworkaccessmanager.cpp 882  0x7ffd166f3f02 
    19 QNetworkAccessManager::post                    qnetworkaccessmanager.cpp 897  0x7ffd166f3fe9 
    20 ApiConnectorMgr::postPingData                  ApiConnectorMgr.cpp       572  0x7ff7815613ab 
    21 ApiConnectorMgr::updateCloudServerStatus       ApiConnectorMgr.cpp       1078 0x7ff7815614ce 
    22 ApiConnectorMgr::ApiConnectorMgr               ApiConnectorMgr.cpp       58   0x7ff781556f18 
    23 MainWindow::MainWindow                         mainwindow.cpp            121  0x7ff78143bbf8 
    24 main                                           main.cpp                  122  0x7ff781438636 
    25 invoke_main                                    exe_common.inl            65   0x7ff781598274 
    26 __scrt_common_main_seh                         exe_common.inl            253  0x7ff781598137 
    27 __scrt_common_main                             exe_common.inl            296  0x7ff781597ffe 
    28 mainCRTStartup                                 exe_main.cpp              17   0x7ff781598299 
    29 BaseThreadInitThunk                            KERNEL32                       0x7ffd67e54034 
    30 RtlUserThreadStart                             ntdll                          0x7ffd67fa3691 
    

    The lock seems to come from a QMutexLocker in qsslsocket_openssl11.cpp

    qsslsocket_openssl11.cpp line 83
    bool QSslSocketPrivate::ensureLibraryLoaded()
    {
        if (!q_resolveOpenSslSymbols())
            return false;
    
        const QMutexLocker locker(qt_opensslInitMutex);
    [interrupted here]
    ->   if (!s_libraryLoaded) {
            // Initialize OpenSSL.
            if (q_OPENSSL_init_ssl(0, nullptr) != 1)
                return false;
            q_SSL_load_error_strings();
            q_OpenSSL_add_all_algorithms();
    
            QSslSocketBackendPrivate::s_indexForSSLExtraData
                = q_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0L, nullptr, nullptr,
                                            nullptr, nullptr);
    
            // Initialize OpenSSL's random seed.
            if (!q_RAND_status()) {
                qWarning("Random number generator not seeded, disabling SSL support");
                return false;
            }
    
            s_libraryLoaded = true;
        }
        return true;
    }
    

    Thanks for your help!

    aha_1980A 1 Reply Last reply
    0
    • Kent-DorfmanK Offline
      Kent-DorfmanK Offline
      Kent-Dorfman
      wrote on last edited by
      #2
      This post is deleted!
      1 Reply Last reply
      0
      • Kent-DorfmanK Offline
        Kent-DorfmanK Offline
        Kent-Dorfman
        wrote on last edited by
        #3

        have you isolated this behaviour to prove that it only happens in an ssl post connection? what about non-ssl web services with other providers? Does it occur in linux or just windows?

        IIRC the network sockets API must run in the GUI thread so moving it to a different event loop probably isn't a valid work-around. Can someone verify my assertion about the GUI thread and networking???

        Since it seems to occur when initializing the ssl layer what happens if you do an ssl connection that you know will work first, as a way to initialize, then attempt the one that is non-reachable?

        SGaistS 1 Reply Last reply
        0
        • Kent-DorfmanK Kent-Dorfman

          have you isolated this behaviour to prove that it only happens in an ssl post connection? what about non-ssl web services with other providers? Does it occur in linux or just windows?

          IIRC the network sockets API must run in the GUI thread so moving it to a different event loop probably isn't a valid work-around. Can someone verify my assertion about the GUI thread and networking???

          Since it seems to occur when initializing the ssl layer what happens if you do an ssl connection that you know will work first, as a way to initialize, then attempt the one that is non-reachable?

          SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @kent-dorfman No, sockets can be used in other threads but you have to be careful to create them in the thread that will use them.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          2
          • J jojopirato

            Hi!

            Please consider the following scenario on WIndows 10 x64 and Qt 5.12.4:
            Use a computer with an ethernet connection with internet access with this setup:
            PC - ethernet cable 1- ethernet switch - ethernet cable 2 - internet gateway
            Now Windows will not immediately detect that the ethernet interface is down when we unplug ethernet cable 2.

            Now make sure you have internet access, unplug ethernet cable 2, make a post request with QNetworkAccessManager from the gui thread. the gui thread freezes for 10-20 seconds until post returns.

            I have compiled this in debug mode and interrupted the process, here is the call stack:

            Note that nplugging ethernet cable 1 instead of ethernet cable 2 won't freeze the thread (as the ethernet interface will be down I guess.)

            1  NtWaitForSingleObject                          ntdll                          0x7ffd67fcaa24 
            2  WaitForSingleObjectEx                          KERNELBASE                     0x7ffd64339252 
            3  QMutexPrivate::wait                            qmutex_win.cpp            64   0x7ffd1335bf5c 
            4  QBasicMutex::lockInternal                      qmutex.cpp                573  0x7ffd1335b8c4 
            5  QBasicMutex::lockInternal                      qmutex.cpp                490  0x7ffd1335b658 
            6  QBasicMutex::lock                              qmutex.h                  80   0x7ffd13320184 
            7  QRecursiveMutexPrivate::lock                   qmutex.cpp                707  0x7ffd1335d69f 
            8  QMutex::lock                                   qmutex.cpp                226  0x7ffd1335bd51 
            9  QMutexLocker::QMutexLocker                     qmutex.h                  207  0x7ffd1331a48d 
            10 QSslSocketPrivate::ensureLibraryLoaded         qsslsocket_openssl11.cpp  90   0x7ffd168cdbf1 
            11 QSslSocketPrivate::supportsSsl                 qsslsocket_openssl.cpp    497  0x7ffd168b7f79 
            12 QSslSocketPrivate::ensureInitialized           qsslsocket_openssl.cpp    509  0x7ffd168b7fe9 
            13 QSslConfigurationPrivate::defaultConfiguration qsslsocket.cpp            2280 0x7ffd168980fe 
            14 QSslConfiguration::defaultConfiguration        qsslconfiguration.cpp     1023 0x7ffd16887233 
            15 QNetworkRequest::sslConfiguration              qnetworkrequest.cpp       675  0x7ffd1671eccb 
            16 QNetworkReplyHttpImpl::QNetworkReplyHttpImpl   qnetworkreplyhttpimpl.cpp 193  0x7ffd167d04ae 
            17 QNetworkAccessManager::createRequest           qnetworkaccessmanager.cpp 1480 0x7ffd166f5f72 
            18 QNetworkAccessManager::post                    qnetworkaccessmanager.cpp 882  0x7ffd166f3f02 
            19 QNetworkAccessManager::post                    qnetworkaccessmanager.cpp 897  0x7ffd166f3fe9 
            20 ApiConnectorMgr::postPingData                  ApiConnectorMgr.cpp       572  0x7ff7815613ab 
            21 ApiConnectorMgr::updateCloudServerStatus       ApiConnectorMgr.cpp       1078 0x7ff7815614ce 
            22 ApiConnectorMgr::ApiConnectorMgr               ApiConnectorMgr.cpp       58   0x7ff781556f18 
            23 MainWindow::MainWindow                         mainwindow.cpp            121  0x7ff78143bbf8 
            24 main                                           main.cpp                  122  0x7ff781438636 
            25 invoke_main                                    exe_common.inl            65   0x7ff781598274 
            26 __scrt_common_main_seh                         exe_common.inl            253  0x7ff781598137 
            27 __scrt_common_main                             exe_common.inl            296  0x7ff781597ffe 
            28 mainCRTStartup                                 exe_main.cpp              17   0x7ff781598299 
            29 BaseThreadInitThunk                            KERNEL32                       0x7ffd67e54034 
            30 RtlUserThreadStart                             ntdll                          0x7ffd67fa3691 
            

            The lock seems to come from a QMutexLocker in qsslsocket_openssl11.cpp

            qsslsocket_openssl11.cpp line 83
            bool QSslSocketPrivate::ensureLibraryLoaded()
            {
                if (!q_resolveOpenSslSymbols())
                    return false;
            
                const QMutexLocker locker(qt_opensslInitMutex);
            [interrupted here]
            ->   if (!s_libraryLoaded) {
                    // Initialize OpenSSL.
                    if (q_OPENSSL_init_ssl(0, nullptr) != 1)
                        return false;
                    q_SSL_load_error_strings();
                    q_OpenSSL_add_all_algorithms();
            
                    QSslSocketBackendPrivate::s_indexForSSLExtraData
                        = q_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0L, nullptr, nullptr,
                                                    nullptr, nullptr);
            
                    // Initialize OpenSSL's random seed.
                    if (!q_RAND_status()) {
                        qWarning("Random number generator not seeded, disabling SSL support");
                        return false;
                    }
            
                    s_libraryLoaded = true;
                }
                return true;
            }
            

            Thanks for your help!

            aha_1980A Offline
            aha_1980A Offline
            aha_1980
            Lifetime Qt Champion
            wrote on last edited by aha_1980
            #5

            Hi @jojopirato,

            there are several reports of similar behavior, e.g. https://bugreports.qt.io/browse/QTBUG-60916 and all were closed as invalid.

            Timur stated there, that QNAM already operates in an own thread. So if you encounter freezes, that is either a bug or a mis-use of the API.

            Can you show a minimal example that illustrates that blocking behavior?

            Regards

            Qt has to stay free or it will die.

            1 Reply Last reply
            0
            • J Offline
              J Offline
              jojopirato
              wrote on last edited by
              #6

              Hi, I have submitted a QT bug with an example and an updated procedure here:

              https://bugreports.qt.io/browse/QTBUG-77370

              1 Reply Last reply
              2

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved