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
_______________________________________________
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"