RFC: jemalloc: qdbus sigsegv in malloc_init
Gustau Pérez i Querol
gperez at entel.upc.edu
Mon May 21 11:16:44 UTC 2012
>>
> Now let me dig into qthread_unix.cpp, see how QThreadData::current()
> works:
>
> QThreadData *QThreadData::current()
> {
> QThreadData *data = get_thread_data();
> if (!data) {
> void *a;
> if
> (QInternal::activateCallbacks(QInternal::AdoptCurrentThread, &a)) {
> QThread *adopted = static_cast<QThread*>(a);
> Q_ASSERT(adopted);
> data = QThreadData::get2(adopted);
> set_thread_data(data);
> adopted->d_func()->running = true;
> adopted->d_func()->finished = false;
> static_cast<QAdoptedThread *>(adopted)->init();
> } else {
> data = new QThreadData;
> QT_TRY {
> set_thread_data(data);
> data->thread = new QAdoptedThread(data);
> } QT_CATCH(...) {
> clear_thread_data();
> data->deref();
> data = 0;
> QT_RETHROW;
> }
> data->deref();
> }
> if (!QCoreApplicationPrivate::theMainThread)
> QCoreApplicationPrivate::theMainThread = data->thread;
> }
> return data;
> }
>
> it calls get_thread_data(), if it returns NULL, it create a new
> thread, and try to
> set the new thread as "current thread data", it calls set_thread_data().
>
> let's see how get_thread_data() and set_thread_data() work :
>
> static QThreadData *get_thread_data()
> {
> #ifdef Q_OS_SYMBIAN
> return reinterpret_cast<QThreadData *>(Dll::Tls());
> #else
> pthread_once(¤t_thread_data_once,
> create_current_thread_data_key);
> return reinterpret_cast<QThreadData
> *>(pthread_getspecific(current_thread_data_key));
> #endif
> }
>
> static void set_thread_data(QThreadData *data)
> {
> #ifdef Q_OS_SYMBIAN
> qt_symbian_throwIfError(Dll::SetTls(data));
> #endif
> pthread_once(¤t_thread_data_once,
> create_current_thread_data_key);
> pthread_setspecific(current_thread_data_key, data);
> }
>
>
> They just use pthread_getspecific and pthread_setspecific, the
> current_thread_data_key was only
> created once which is guarded by pthread_once(), but as you know, the
> key has already
> been deleted by Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key)
> which is a global
> object which has been destructed early, the key is no longer
> recreated, it is a stale key.
>
I was able to debug until the point where qthread_unix.cpp spawns a
new thread because the get_thread_data call returns 0. I was unable to
reach the full analysis, but now I get it. The explanation seems fine to
me, thanks.
What I don't get is why it works in stable. The functions registered
to be executed at exit (atexit_register hasn't changed) get registered
in same order in both branches (at least I checked them by printing the
two atexit structures when calling exit in both stable and head).
Wouldn't that mean that the problem of deleting the
current_thread_data_key should happen in both branches?
Gus
More information about the freebsd-current
mailing list