From bf66eebbc28b1f405a49a68d3f6c341d433159ea Mon Sep 17 00:00:00 2001 From: jian liang Date: Sat, 18 Feb 2012 08:43:29 +0800 Subject: Fix to exit of adopted thread watcher in Windows Don't register the thread handle and QThread object pointer to watch list for adopted thread watcher thread in Windows. Otherwise the watcher thread will never exit and can't clean up its own QThreadData and QAdoptedThread object. Task-number: QTBUG-23961 Change-Id: Ia84326cf3cfd978d2b003ccc1bb6861db950e899 Reviewed-by: Friedemann Kleint Reviewed-by: Joerg Bornemann --- src/corelib/thread/qthread_win.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'src/corelib/thread/qthread_win.cpp') diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index afcfb2c949..38fb6ef8dd 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -72,7 +72,7 @@ QT_BEGIN_NAMESPACE void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread); -void qt_adopted_thread_watcher_function(void *); +DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID); static DWORD qt_current_thread_data_tls_index = TLS_OUT_OF_INDEXES; void qt_create_tls() @@ -147,7 +147,7 @@ void QAdoptedThread::init() static QVector qt_adopted_thread_handles; static QVector qt_adopted_qthreads; static QMutex qt_adopted_thread_watcher_mutex; -static HANDLE qt_adopted_thread_watcher_handle = 0; +static DWORD qt_adopted_thread_watcher_id = 0; static HANDLE qt_adopted_thread_wakeup = 0; /*! \internal @@ -158,18 +158,25 @@ static HANDLE qt_adopted_thread_wakeup = 0; void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread) { QMutexLocker lock(&qt_adopted_thread_watcher_mutex); + + if (GetCurrentThreadId() == qt_adopted_thread_watcher_id) { +#if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600)) + CloseHandle(adoptedThreadHandle); +#endif + return; + } + qt_adopted_thread_handles.append(adoptedThreadHandle); qt_adopted_qthreads.append(qthread); // Start watcher thread if it is not already running. - if (qt_adopted_thread_watcher_handle == 0) { + if (qt_adopted_thread_watcher_id == 0) { if (qt_adopted_thread_wakeup == 0) { qt_adopted_thread_wakeup = CreateEvent(0, false, false, 0); qt_adopted_thread_handles.prepend(qt_adopted_thread_wakeup); } - qt_adopted_thread_watcher_handle = - (HANDLE)_beginthread(qt_adopted_thread_watcher_function, 0, NULL); + CreateThread(0, 0, qt_adopted_thread_watcher_function, 0, 0, &qt_adopted_thread_watcher_id); } else { SetEvent(qt_adopted_thread_wakeup); } @@ -180,13 +187,13 @@ void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread) When this happens it derefs the QThreadData for the adopted thread to make sure it gets cleaned up properly. */ -void qt_adopted_thread_watcher_function(void *) +DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID) { forever { qt_adopted_thread_watcher_mutex.lock(); if (qt_adopted_thread_handles.count() == 1) { - qt_adopted_thread_watcher_handle = 0; + qt_adopted_thread_watcher_id = 0; qt_adopted_thread_watcher_mutex.unlock(); break; } @@ -244,6 +251,12 @@ void qt_adopted_thread_watcher_function(void *) qt_adopted_qthreads.remove(qthreadIndex); } } + + QThreadData *threadData = reinterpret_cast(TlsGetValue(qt_current_thread_data_tls_index)); + if (threadData) + threadData->deref(); + + return 0; } #if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) -- cgit v1.2.3