summaryrefslogtreecommitdiffstats
path: root/src/testlib/qtestcase.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2022-05-02 18:52:51 -0700
committerThiago Macieira <thiago.macieira@intel.com>2022-05-20 12:01:37 -0700
commit29dd43d5ab18ec01df0d173e974d261afd16a311 (patch)
tree67704bc39543fc378bf1fe2a4ea660f45098fae6 /src/testlib/qtestcase.cpp
parentc4600b2e25d4e7e7f7d6d5ab3d1819d5ec35caa2 (diff)
FatalSignalHandler: remember the previous signal's handler
And only restore those signals, instead of iterating over all possible signals, instead of attempting to restore to SIG_DFL. Also, as a consequence, we will install our handler even if there was already a handler installed for the signal. Pick-to: 6.3 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16eb756685f4e8b8 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Diffstat (limited to 'src/testlib/qtestcase.cpp')
-rw-r--r--src/testlib/qtestcase.cpp64
1 files changed, 23 insertions, 41 deletions
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 122c85ff27..7dbe13bb6d 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -1836,16 +1836,19 @@ using FatalSignalHandler = WindowsFaultHandler;
class FatalSignalHandler
{
public:
+ static constexpr std::array fatalSignals = {
+ SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGPIPE, SIGTERM
+ };
+ using OldActionsArray = std::array<struct sigaction, fatalSignals.size()>;
+
FatalSignalHandler()
{
pauseOnCrash = qEnvironmentVariableIsSet("QTEST_PAUSE_ON_CRASH");
- sigemptyset(&handledSignals);
-
- const int fatalSignals[] = {
- SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGPIPE, SIGTERM };
-
struct sigaction act;
memset(&act, 0, sizeof(act));
+ act.sa_handler = SIG_DFL;
+ oldActions().fill(act);
+
// Remove the handler after it is invoked.
act.sa_flags = SA_RESETHAND;
@@ -1882,39 +1885,14 @@ public:
for (int signal : fatalSignals)
sigaddset(&act.sa_mask, signal);
- // The destructor can only restore SIG_DFL, so only register for signals
- // that had default handling previously.
- const auto isDefaultHandler = [](const struct sigaction &old) {
-# ifdef SA_SIGINFO
- // void sa_sigaction(int, siginfo_t *, void *) is never the default:
- if (old.sa_flags & SA_SIGINFO)
- return false;
-# endif
- // Otherwise, the handler is void sa_handler(int) but may be
- // SIG_DFL (default action) or SIG_IGN (ignore signal):
- return old.sa_handler == SIG_DFL;
- };
-
- struct sigaction oldact;
- for (int signal : fatalSignals) {
- // Registering reveals the existing handler:
- if (sigaction(signal, &act, &oldact))
- continue; // Failed to set our handler; nothing to restore.
- if (isDefaultHandler(oldact))
- sigaddset(&handledSignals, signal);
- else // Restore non-default handler:
- sigaction(signal, &oldact, nullptr);
- }
+ for (size_t i = 0; i < fatalSignals.size(); ++i)
+ sigaction(fatalSignals[i], &act, &oldActions()[i]);
}
~FatalSignalHandler()
{
- // Restore the default signal handler in place of ours.
+ // Restore the default signal handlers 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::actionHandler;
@@ -1924,20 +1902,26 @@ public:
};
struct sigaction action;
- for (int signum = 1; signum < 32; ++signum) {
- if (!sigismember(&handledSignals, signum))
- continue;
- if (sigaction(signum, nullptr, &action))
+ for (size_t i = 0; i < fatalSignals.size(); ++i) {
+ struct sigaction &act = oldActions()[i];
+ if (act.sa_flags == 0 && act.sa_handler == SIG_DFL)
+ continue; // Already the default
+ if (sigaction(fatalSignals[i], nullptr, &action))
continue; // Failed to query present handler
-
if (isOurs(action))
- sigaction(signum, &act, nullptr);
+ sigaction(fatalSignals[i], &act, nullptr);
}
}
private:
Q_DISABLE_COPY_MOVE(FatalSignalHandler)
+ static OldActionsArray &oldActions()
+ {
+ Q_CONSTINIT static OldActionsArray oldActions {};
+ return oldActions;
+ }
+
static void actionHandler(int signum, siginfo_t * /* info */, void * /* ucontext */)
{
const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime());
@@ -1961,8 +1945,6 @@ private:
{
actionHandler(signum, nullptr, nullptr);
}
-
- sigset_t handledSignals;
static bool pauseOnCrash;
};
bool FatalSignalHandler::pauseOnCrash = false;