QThread/Unix: extract duplicate code
Extract function terminate_on_exception() that de-duplicates the #ifdef'ery around the try/catch and the handling of the pthread cancellation pseudo-exception. Apart from de-duplicating complex code, it will also help suppressing a ubsan false positive, which is why we're picking it all the way to 5.15. Pick-to: 6.3 6.2 5.15 Change-Id: I99ad2c0618b8dc30801931df09400c6611d9f9e4 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
c760fba40e
commit
f0ffe35149
@ -284,6 +284,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)
|
||||
@ -291,10 +314,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);
|
||||
|
||||
@ -336,20 +356,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
|
||||
@ -361,10 +368,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();
|
||||
|
||||
@ -396,20 +400,7 @@ void QThreadPrivate::finish(void *arg)
|
||||
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
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user