Deadlock in QHostInfoLookupManager (QTBUG-14092)



  • Hi,

    We have heterogenous x32 Windows application, unmanaged and managed .NET code, Qt 4.8.2 + QtWebKit.

    There is a strange issue that looks like exactly as "QTBUG-14092":https://bugreports.qt-project.org/browse/QTBUG-14092. (See "Paul Kolomiets added a comment - 01/Oct/10 10:18 AM"). The runtime sends DLL_PROCESS_DETACH event to QtNetwork4.dll and then application waits for INFINITE when destroying QHostInfoLookupManager singleton.

    I have only full dump of the application compiled with release version of Qt-libraries, so there's no symbols supported. But i've restored stack trace manually:

    @ntdll!NtWaitForSingleObject
    KERNELBASE!WaitForSingleObjectEx
    kernel32!WaitForSingleObjectExImplementation
    kernel32!WaitForSingleObject
    QtCore4!QWaitCondition::wait()

    bool QWaitConditionPrivate::wait(QWaitConditionEvent *wce, unsigned long time = 0xFFFFFFFF)
    {
    // wait for the event
    bool ret = false;
    switch (WaitForSingleObject(wce->event, time)) { <-- here
    default: break;

    case WAIT_OBJECT_0:
        ret = true;
        break;
    }
    return ret;
    

    }

    QThreadPoolPrivate::waitForDone(int msecs = 0xFFFFFFFF)

    bool QThreadPoolPrivate::waitForDone(int msecs)
    {
    QMutexLocker locker(&mutex);
    if (msecs < 0) {
    while (!(queue.isEmpty() && activeThreads == 0))
    noActiveThreads.wait(locker.mutex()); <-- here
    } else {
    QElapsedTimer timer;
    timer.start();
    int t;
    while (!(queue.isEmpty() && activeThreads == 0) &&
    ((t = msecs - timer.elapsed()) > 0))
    noActiveThreads.wait(locker.mutex(), t);
    }
    return queue.isEmpty() && activeThreads == 0;
    }

    QThreadPool::waitForDone()

    void QThreadPool::waitForDone()
    {
    Q_D(QThreadPool);
    d->waitForDone(); <-- here
    d->reset();
    }

    QHostInfoLookupManager::clear()

    void QHostInfoLookupManager::clear()
    {
    {
    QMutexLocker locker(&mutex);
    qDeleteAll(postponedLookups);
    qDeleteAll(scheduledLookups);
    qDeleteAll(finishedLookups);
    postponedLookups.clear();
    scheduledLookups.clear();
    finishedLookups.clear();
    }

    threadPool.waitForDone();  <-- here
    cache.clear();
    

    }

    QHostInfoLookupManager::~QHostInfoLookupManager()

    QHostInfoLookupManager::~QHostInfoLookupManager()
    {
    wasDeleted = true;

    // don't qDeleteAll currentLookups, the QThreadPool has ownership
    clear(); <-- here
    

    }

    6224b520()

    6224b520 56 push esi
    6224b521 8bf1 mov esi,ecx
    6224b523 e8c8f6ffff call QtNetwork4!QHostInfo::~QHostInfo+0xc70 (6224abf0) <-- here
    6224b528 f644240801 test byte ptr [esp+8],1
    6224b52d 7409 je QtNetwork4!QHostInfo::fromName+0x458 (6224b538)
    6224b52f 56 push esi
    6224b530 e85f7c0300 call QtNetwork4!QUdpSocket::metaObject+0x324 (62283194)
    6224b535 83c404 add esp,4
    6224b538 8bc6 mov eax,esi
    6224b53a 5e pop esi
    6224b53b c20400 ret 4

    62296f50()

    62296f50 a108d72d62 mov eax,dword ptr [QtNetwork4!QBearerEnginePlugin::staticMetaObject+0x128 (622dd708)]
    62296f55 8b08 mov ecx,dword ptr [eax]
    62296f57 85c9 test ecx,ecx
    62296f59 7420 je QtNetwork4!QUdpSocket::metaObject+0x1410b (62296f7b)
    62296f5b 8b11 mov edx,dword ptr [ecx]
    62296f5d 8b420c mov eax,dword ptr [edx+0Ch]
    62296f60 6a01 push 1
    62296f62 ffd0 call eax // 6224b520 is stored in memory, see 62296f50 mov instruction and others <-- here
    62296f64 8b0d08d72d62 mov ecx,dword ptr [QtNetwork4!QBearerEnginePlugin::staticMetaObject+0x128 (622dd708)]
    62296f6a c70100000000 mov dword ptr [ecx],0
    62296f70 8b1508d72d62 mov edx,dword ptr [QtNetwork4!QBearerEnginePlugin::staticMetaObject+0x128 (622dd708)]
    62296f76 c6420401 mov byte ptr [edx+4],1
    62296f7a c3 ret
    62296f7b a108d72d62 mov eax,dword ptr [QtNetwork4!QBearerEnginePlugin::staticMetaObject+0x128 (622dd708)]
    62296f80 c70000000000 mov dword ptr [eax],0
    62296f86 8b0d08d72d62 mov ecx,dword ptr [QtNetwork4!QBearerEnginePlugin::staticMetaObject+0x128 (622dd708)]
    62296f8c c6410401 mov byte ptr [ecx+4],1
    62296f90 c3 ret

    _CRT_INIT(…)
    __DllMainCRTStartup(QtNetwork4)
    DllEntryPoint(hInstance = QtNetwork4, fdwReason = DLL_PROCESS_DETACH, 1)
    ntdll!LdrpCallInitRoutine
    ntdll!LdrShutdownProcess
    ntdll!RtlExitUserProcess
    kernel32!ExitProcessStub
    mscoreei!RuntimeDesc::ShutdownAllActiveRuntimes
    mscoreei!CorExitProcess
    mscoree!ShellShim_CorExitProcess
    msvcr100!__crtCorExitProcess
    msvcr100!__crtExitProcess
    msvcr100!_cinit
    msvcr100!exit
    QtWebHost
    kernel32!BaseThreadInitThunk
    ntdll!__RtlUserThreadStart
    ntdll!_RtlUserThreadStart
    @

    There is only one live thread in the application:

    @0:000> ~#
    . 0 Id: 11bc.287c Suspend: 0 Teb: 7efdd000 Unfrozen
    Start: QtWebHost+0x724cc (00f724cc)
    Priority: 0 Priority class: 32 Affinity: 3
    @

    The QTBUG-14092 issue was closed due to expiration and Bradley said:

    "To be perfectly honest, I don't know what to do with this task. I seem to recall seeing cases where Windows threads would disappear at application exit, yet the HANDLE to those threads would not be signaled (meaning your app would deadlock if waiting on the handle).

    I am tempted to simply mark this as "Out of Scope", since, as Thiago says, we do not test nor really support unloading the Qt libraries from the application once they have been loaded."

    The question is what can I do with this issue? Is there any chance to fix this issue?



  • I just had a related issue (running Qt 4.6.1), and asked on StackOverflow: (http://stackoverflow.com/questions/3454315/is-it-possible-to-pin-a-dll-in-memory-to-prevent-unloading)

    I got a comment linking to http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx, which essentially says "don't do more than the absolute critical on shutdown".

    So, closing that threadpool is unnecessary. Should not be done.

    I suppose the workaround is to patch Qt (or upgrade, if things have changed...)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.