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
_______________________________________________
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"

Reply via email to