diff options
Diffstat (limited to 'src/corelib/thread/qthread_unix.cpp')
-rw-r--r-- | src/corelib/thread/qthread_unix.cpp | 85 |
1 files changed, 42 insertions, 43 deletions
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 659d5fb03c..a27782d37c 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -169,8 +169,7 @@ static void set_thread_data(QThreadData *data) static void clear_thread_data() { - currentThreadData = nullptr; - pthread_setspecific(current_thread_data_key, nullptr); + set_thread_data(nullptr); } template <typename T> @@ -278,6 +277,29 @@ static void setCurrentThreadName(const char *name) } #endif +namespace { +template <typename T> +void terminate_on_exception(T &&t) +{ +#ifndef QT_NO_EXCEPTIONS + try { +#endif + std::forward<T>(t)(); +#ifndef QT_NO_EXCEPTIONS +#ifdef __GLIBCXX__ + // POSIX thread cancellation under glibc is implemented by throwing an exception + // of this type. Do what libstdc++ is doing and handle it specially in order not to + // abort the application if user's code calls a cancellation function. + } catch (abi::__forced_unwind &) { + throw; +#endif // __GLIBCXX__ + } catch (...) { + qTerminate(); + } +#endif // QT_NO_EXCEPTIONS +} +} // unnamed namespace + void *QThreadPrivate::start(void *arg) { #if !defined(Q_OS_ANDROID) @@ -285,10 +307,7 @@ void *QThreadPrivate::start(void *arg) #endif pthread_cleanup_push(QThreadPrivate::finish, arg); -#ifndef QT_NO_EXCEPTIONS - try -#endif - { + terminate_on_exception([&] { QThread *thr = reinterpret_cast<QThread *>(arg); QThreadData *data = QThreadData::get2(thr); @@ -296,11 +315,13 @@ void *QThreadPrivate::start(void *arg) QMutexLocker locker(&thr->d_func()->mutex); // do we need to reset the thread priority? - if (int(thr->d_func()->priority) & ThreadPriorityResetFlag) { + if (thr->d_func()->priority & ThreadPriorityResetFlag) { thr->d_func()->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag)); } - data->threadId.storeRelaxed(to_HANDLE(pthread_self())); + // threadId is set in QThread::start() + Q_ASSERT(pthread_equal(from_HANDLE<pthread_t>(data->threadId.loadRelaxed()), + pthread_self())); set_thread_data(data); data->ref(); @@ -314,10 +335,10 @@ void *QThreadPrivate::start(void *arg) // Sets the name of the current thread. We can only do this // when the thread is starting, as we don't have a cross // platform way of setting the name of an arbitrary thread. - if (Q_LIKELY(thr->objectName().isEmpty())) + if (Q_LIKELY(thr->d_func()->objectName.isEmpty())) setCurrentThreadName(thr->metaObject()->className()); else - setCurrentThreadName(thr->objectName().toLocal8Bit()); + setCurrentThreadName(std::exchange(thr->d_func()->objectName, {}).toLocal8Bit()); } #endif @@ -327,20 +348,7 @@ void *QThreadPrivate::start(void *arg) pthread_testcancel(); #endif thr->run(); - } -#ifndef QT_NO_EXCEPTIONS -#ifdef __GLIBCXX__ - // POSIX thread cancellation under glibc is implemented by throwing an exception - // of this type. Do what libstdc++ is doing and handle it specially in order not to - // abort the application if user's code calls a cancellation function. - catch (const abi::__forced_unwind &) { - throw; - } -#endif // __GLIBCXX__ - catch (...) { - qTerminate(); - } -#endif // QT_NO_EXCEPTIONS + }); // This pop runs finish() below. It's outside the try/catch (and has its // own try/catch) to prevent finish() to be run in case an exception is @@ -352,10 +360,7 @@ void *QThreadPrivate::start(void *arg) void QThreadPrivate::finish(void *arg) { -#ifndef QT_NO_EXCEPTIONS - try -#endif - { + terminate_on_exception([&] { QThread *thr = reinterpret_cast<QThread *>(arg); QThreadPrivate *d = thr->d_func(); @@ -384,21 +389,10 @@ void QThreadPrivate::finish(void *arg) d->interruptionRequested = false; d->isInFinish = false; + d->data->threadId.storeRelaxed(nullptr); + d->thread_done.wakeAll(); - } -#ifndef QT_NO_EXCEPTIONS -#ifdef __GLIBCXX__ - // POSIX thread cancellation under glibc is implemented by throwing an exception - // of this type. Do what libstdc++ is doing and handle it specially in order not to - // abort the application if user's code calls a cancellation function. - catch (const abi::__forced_unwind &) { - throw; - } -#endif // __GLIBCXX__ - catch (...) { - qTerminate(); - } -#endif // QT_NO_EXCEPTIONS + }); } @@ -667,7 +661,7 @@ void QThread::start(Priority priority) // could not set scheduling hints, fallback to inheriting them // we'll try again from inside the thread pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); - d->priority = Priority(priority | ThreadPriorityResetFlag); + d->priority = std::underlying_type<Priority>::type(priority) | ThreadPriorityResetFlag; } break; } @@ -698,7 +692,10 @@ void QThread::start(Priority priority) pthread_attr_setthreadname(&attr, metaObject()->className()); else pthread_attr_setthreadname(&attr, objectName().toLocal8Bit()); +#else + d->objectName = objectName(); #endif + pthread_t threadId; int code = pthread_create(&threadId, &attr, QThreadPrivate::start, this); if (code == EPERM) { @@ -755,6 +752,8 @@ bool QThread::wait(QDeadlineTimer deadline) if (!d->thread_done.wait(locker.mutex(), deadline)) return false; } + Q_ASSERT(d->data->threadId.loadRelaxed() == nullptr); + return true; } |