diff options
Diffstat (limited to 'src/corelib/thread/qthread_unix.cpp')
-rw-r--r-- | src/corelib/thread/qthread_unix.cpp | 151 |
1 files changed, 97 insertions, 54 deletions
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 69a11b2b62..6540f02f34 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -61,6 +61,10 @@ #include "qdebug.h" +#ifdef __GLIBCXX__ +#include <cxxabi.h> +#endif + #include <sched.h> #include <errno.h> @@ -324,49 +328,70 @@ void *QThreadPrivate::start(void *arg) #endif pthread_cleanup_push(QThreadPrivate::finish, arg); - QThread *thr = reinterpret_cast<QThread *>(arg); - QThreadData *data = QThreadData::get2(thr); - +#ifndef QT_NO_EXCEPTIONS + try +#endif { - QMutexLocker locker(&thr->d_func()->mutex); + QThread *thr = reinterpret_cast<QThread *>(arg); + QThreadData *data = QThreadData::get2(thr); - // do we need to reset the thread priority? - if (int(thr->d_func()->priority) & ThreadPriorityResetFlag) { - thr->d_func()->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag)); - } - - data->threadId.store(to_HANDLE(pthread_self())); - set_thread_data(data); + { + QMutexLocker locker(&thr->d_func()->mutex); - data->ref(); - data->quitNow = thr->d_func()->exited; - } + // do we need to reset the thread priority? + if (int(thr->d_func()->priority) & ThreadPriorityResetFlag) { + thr->d_func()->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag)); + } - if (data->eventDispatcher.load()) // custom event dispatcher set? - data->eventDispatcher.load()->startingUp(); - else - createEventDispatcher(data); + data->threadId.store(to_HANDLE(pthread_self())); + set_thread_data(data); -#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX)) - { - // sets the name of the current thread. - QString objectName = thr->objectName(); + data->ref(); + data->quitNow = thr->d_func()->exited; + } - pthread_t thread_id = from_HANDLE<pthread_t>(data->threadId.load()); - if (Q_LIKELY(objectName.isEmpty())) - setCurrentThreadName(thread_id, thr->metaObject()->className()); + if (data->eventDispatcher.load()) // custom event dispatcher set? + data->eventDispatcher.load()->startingUp(); else - setCurrentThreadName(thread_id, objectName.toLocal8Bit()); - } + createEventDispatcher(data); + +#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX)) + { + // sets the name of the current thread. + QString objectName = thr->objectName(); + + pthread_t thread_id = from_HANDLE<pthread_t>(data->threadId.load()); + if (Q_LIKELY(objectName.isEmpty())) + setCurrentThreadName(thread_id, thr->metaObject()->className()); + else + setCurrentThreadName(thread_id, objectName.toLocal8Bit()); + } #endif - emit thr->started(QThread::QPrivateSignal()); + emit thr->started(QThread::QPrivateSignal()); #if !defined(Q_OS_ANDROID) - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - pthread_testcancel(); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_testcancel(); #endif - thr->run(); + 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 + // thrown. pthread_cleanup_pop(1); return 0; @@ -374,35 +399,53 @@ void *QThreadPrivate::start(void *arg) void QThreadPrivate::finish(void *arg) { - QThread *thr = reinterpret_cast<QThread *>(arg); - QThreadPrivate *d = thr->d_func(); +#ifndef QT_NO_EXCEPTIONS + try +#endif + { + QThread *thr = reinterpret_cast<QThread *>(arg); + QThreadPrivate *d = thr->d_func(); - QMutexLocker locker(&d->mutex); + QMutexLocker locker(&d->mutex); - d->isInFinish = true; - d->priority = QThread::InheritPriority; - void *data = &d->data->tls; - locker.unlock(); - emit thr->finished(QThread::QPrivateSignal()); - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); - QThreadStorageData::finish((void **)data); - locker.relock(); - - QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.load(); - if (eventDispatcher) { - d->data->eventDispatcher = 0; + d->isInFinish = true; + d->priority = QThread::InheritPriority; + void *data = &d->data->tls; locker.unlock(); - eventDispatcher->closingDown(); - delete eventDispatcher; + emit thr->finished(QThread::QPrivateSignal()); + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QThreadStorageData::finish((void **)data); locker.relock(); - } - d->running = false; - d->finished = true; - d->interruptionRequested = false; + QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.load(); + if (eventDispatcher) { + d->data->eventDispatcher = 0; + locker.unlock(); + eventDispatcher->closingDown(); + delete eventDispatcher; + locker.relock(); + } + + d->running = false; + d->finished = true; + d->interruptionRequested = false; - d->isInFinish = false; - d->thread_done.wakeAll(); + d->isInFinish = false; + 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 } |