Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 May 2012 13:17:04 +0200
From:      =?UTF-8?B?R3VzdGF1IFDDqXJleiBpIFF1ZXJvbA==?= <gperez@entel.upc.edu>
To:        davidxu@freebsd.org
Cc:        Konstantin Belousov <kostikbel@gmail.com>, Alberto Villa <avilla@freebsd.org>, FreeBSD current <freebsd-current@freebsd.org>, David Xu <listlog2011@gmail.com>
Subject:   Re: RFC: jemalloc: qdbus sigsegv in malloc_init
Message-ID:  <4FBA2430.6040301@entel.upc.edu>
In-Reply-To: <4FB9B649.8020906@gmail.com>
References:  <4F9E9E06.4070004@entel.upc.edu> <4FB88925.4070008@gmail.com> <CAJp7RHaOkEzyfD5e6pLMSBxvCBYCn9BWv=9BWu0CYsQHzGyFdg@mail.gmail.com> <20120520172419.GQ2358@deviant.kiev.zoral.com.ua> <4FB9AE7E.6090109@gmail.com> <4FB9B649.8020906@gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

>>
> 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(&current_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(&current_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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4FBA2430.6040301>