summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2022-02-25 12:38:37 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-03-02 14:06:24 +0000
commit58cf75e375676b12e3d22f5d8ff20835d9d22bc8 (patch)
tree2249bdfb750738bee1d54e35e9b24b9342e464a8
parente918e33f493b90c4d2fa8edbbe8af9763909f0da (diff)
Adapt QTest::FatalSignalHandler() to support sa_sigaction when available
We don't currently have a use for the extra parameters, but Samuel Mira's fix to ensure we don't miss fatal signals on Android needs to be able to call the prior handler, which may need these parameters. In the process, check returns from sigaction() and use its nullptr semantics to query first when detecting whether to restore the default when done, rather than setting and then restoring if it turns out we've been replaced in the meantime. Task-number: QTBUG-97652 Change-Id: If30a0db35946c3dceb409ae3f41aa437149472e6 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit fcecaf53f51d4da708a7ef5d05f56f7286d2139c) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/testlib/qtestcase.cpp29
1 files changed, 23 insertions, 6 deletions
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 1e5b8d225f..c22d6e0daa 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -1684,7 +1684,12 @@ public:
struct sigaction act;
memset(&act, 0, sizeof(act));
+# ifdef SA_SIGINFO
+ act.sa_flags |= SA_SIGINFO;
+ act.sa_sigaction = FatalSignalHandler::signal;
+# else
act.sa_handler = FatalSignalHandler::signal;
+# endif
// Remove the handler after it is invoked.
# if !defined(Q_OS_INTEGRITY)
@@ -1746,21 +1751,29 @@ public:
~FatalSignalHandler()
{
#if defined(Q_OS_UNIX) && !defined(Q_OS_WASM)
- // Unregister any of our remaining signal handlers
+ // Restore the default signal handler in place of ours.
+ // If ours has been replaced, leave the replacement alone.
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_DFL;
+ auto isOurs = [](const struct sigaction &old) {
+# ifdef SA_SIGINFO
+ return (old.sa_flags & SA_SIGINFO) && old.sa_sigaction == FatalSignalHandler::signal;
+# else
+ return old.sa_handler == FatalSignalHandler::signal;
+# endif
+ };
struct sigaction oldact;
for (int i = 1; i < 32; ++i) {
if (!sigismember(&handledSignals, i))
continue;
- sigaction(i, &act, &oldact);
+ if (sigaction(i, nullptr, &oldact))
+ continue; // Failed to query present handler
- // If someone overwrote it in the mean time, put it back
- if (oldact.sa_handler != FatalSignalHandler::signal)
- sigaction(i, &oldact, nullptr);
+ if (isOurs(oldact))
+ sigaction(i, &act, nullptr);
}
#endif
}
@@ -1812,7 +1825,11 @@ private:
#endif // defined(Q_OS_WIN)
#if defined(Q_OS_UNIX) && !defined(Q_OS_WASM)
+# ifdef SA_SIGINFO
+ static void signal(int signum, siginfo_t * /* info */, void * /* ucontext */)
+# else
static void signal(int signum)
+#endif
{
const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime());
const int msecsTotalTime = qRound(QTestLog::msecsTotalTime());