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:
Marc Mutz 2021-12-22 15:01:27 +01:00
parent c760fba40e
commit f0ffe35149

View File

@ -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
});
}