diff options
author | Tor Arne Vestbø <tor.arne.vestbo@digia.com> | 2013-06-11 13:05:13 (GMT) |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-06-16 10:39:19 (GMT) |
commit | 8d23f522c29dc2983cf2eae46a9259da326fc8b5 (patch) | |
tree | 877a531eae4a50af3996ccbc8b7e6c7303f2013c /src | |
parent | bd42c14963f1434eb8ca7ba2a432a2f9f970f80a (diff) | |
download | Qt-8d23f522c29dc2983cf2eae46a9259da326fc8b5.zip Qt-8d23f522c29dc2983cf2eae46a9259da326fc8b5.tar.gz Qt-8d23f522c29dc2983cf2eae46a9259da326fc8b5.tar.bz2 |
Fix crash when re-creating QThreadData after initially destroying it
We destroy the thread data for the main thread when the QCoreApplication
is destructed, and then delete the pthread key for the thread data in
the global static destructor function 'destroy_current_thread_data_key'.
The user may have its own Q_DESTRUCTOR_FUNCTION though, which may or may
not run after we've destroyed the key. If it runs after we've destroyed
the key, we'll end up trying to re-create the tread-data, as expected,
but set_thread_data() will fail to persist it, as pthread_setspecific
is called with an invalid key. The result is an infinite recursion:
...
6 in QThreadData::current () at qthread_unix.cpp:216
7 in QObject::QObject (this=0x48e1b30, dd=@0x48e1b40, parent=0x0) at qobject.cpp:703
8 in QThread::QThread (this=0x48e1b30, dd=@0x48e1b40, parent=0x0) at qthread.cpp:396
9 in QAdoptedThread::QAdoptedThread (this=0x48e1b30, data=0x48e1af0) at qthread.cpp:120
10 in QAdoptedThread::QAdoptedThread (this=0x48e1b30, data=0x48e1af0) at qthread.cpp:130
11 in QThreadData::current () at qthread_unix.cpp:219
12 in QObject::QObject (this=0x48e1a20, dd=@0x48e1a30, parent=0x0) at qobject.cpp:703
...
To solve this, we reset current_thread_data_once when destroying the key,
so that subsequent calls to pthread_once to potentially create the key
will call create_current_thread_data_key once more. This means we'll leak
the key for this particular use-case, since we don't end up calling
pthread_key_delete a second time, but this leak is small and happens
typically only for a short duration during application shutdown.
Cherry-picked from qtbase/46667d604fb2ae11a87c0c075a3d2468d02f7bdb.
Change-Id: Iffc372ca530a486cd3efc2237ab02468bdcb5c81
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/thread/qthread_unix.cpp | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 57127a2..d3c0050 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -171,6 +171,12 @@ static void destroy_current_thread_data_key() { pthread_once(¤t_thread_data_once, create_current_thread_data_key); pthread_key_delete(current_thread_data_key); + + // Reset current_thread_data_once in case we end up recreating + // the thread-data in the rare case of QObject construction + // after destroying the QThreadData. + pthread_once_t pthread_once_init = PTHREAD_ONCE_INIT; + current_thread_data_once = pthread_once_init; } Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key) |