FatalSignalHandler: print some more information from siginfo_t
The siginfo_t parameter allows us to show what process sent a signal or the crashing address. Additionally, it allows us to determine if the crashing signal was indeed sent due to a crash. The selftest tst_crashes produces now: $ QTEST_DISABLE_STACK_DUMP=1 ./crashes ********* Start testing of tst_Crashes ********* Config: Using QtTest library 6.4.0, Qt 6.4.0 (x86_64-little_endian-lp64 shared (dynamic) debug build; by GCC 11.2.1 20220420 [revision 691af15031e00227ba6d5935c1d737026cda4129]), opensuse-tumbleweed 20220428 PASS : tst_Crashes::initTestCase() Received signal 11 (SIGSEGV), code 1, for address 0x0000000000000004 Function time: 0ms, total time: 0ms [1] 201995 segmentation fault (core dumped) QTEST_DISABLE_STACK_DUMP=1 ./crashes The last line comes from the shell. The code isn't decoded, but on Linux it's a SEGV_MAPERR. macOS prints exactly the same thing. I've updated one of the expected_crashes_*.txt output that doesn't seem possible (the "Received a fatal error" message does not appear in Qt anywhere). Pick-to: 6.4 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16ebc8391234f0e2 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
68a1f9582b
commit
5e67e7efaa
@ -2074,12 +2074,48 @@ private:
|
|||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void actionHandler(int signum, siginfo_t * /* info */, void * /* ucontext */)
|
template <typename T> static
|
||||||
|
std::enable_if_t<sizeof(std::declval<T>().si_pid) + sizeof(std::declval<T>().si_uid) >= 1>
|
||||||
|
printSentSignalInfo(T *info)
|
||||||
|
{
|
||||||
|
writeToStderr(" sent by PID ", asyncSafeToString(info->si_pid),
|
||||||
|
" UID ", asyncSafeToString(info->si_uid));
|
||||||
|
}
|
||||||
|
static void printSentSignalInfo(...) {}
|
||||||
|
|
||||||
|
template <typename T> static
|
||||||
|
std::enable_if_t<sizeof(std::declval<T>().si_addr) >= 1> printCrashingSignalInfo(T *info)
|
||||||
|
{
|
||||||
|
using HexString = std::array<char, sizeof(quintptr) * 2>;
|
||||||
|
auto toHexString = [](quintptr u, HexString &&r = {}) {
|
||||||
|
int shift = sizeof(quintptr) * 8 - 4;
|
||||||
|
for (size_t i = 0; i < sizeof(quintptr) * 2; ++i, shift -= 4)
|
||||||
|
r[i] = QtMiscUtils::toHexLower(u >> shift);
|
||||||
|
struct iovec vec;
|
||||||
|
vec.iov_base = r.data();
|
||||||
|
vec.iov_len = r.size();
|
||||||
|
return vec;
|
||||||
|
};
|
||||||
|
writeToStderr(", code ", asyncSafeToString(info->si_code),
|
||||||
|
", for address 0x", toHexString(quintptr(info->si_addr)));
|
||||||
|
}
|
||||||
|
static void printCrashingSignalInfo(...) {}
|
||||||
|
|
||||||
|
static void actionHandler(int signum, siginfo_t *info, void * /* ucontext */)
|
||||||
{
|
{
|
||||||
writeToStderr("Received signal ", asyncSafeToString(signum),
|
writeToStderr("Received signal ", asyncSafeToString(signum),
|
||||||
" (SIG", signalName(signum), ")\n");
|
" (SIG", signalName(signum), ")");
|
||||||
printTestRunTime();
|
|
||||||
|
|
||||||
|
bool isCrashingSignal =
|
||||||
|
std::find(crashingSignals.begin(), crashingSignals.end(), signum) != crashingSignals.end();
|
||||||
|
if (isCrashingSignal && (!info || info->si_code <= 0))
|
||||||
|
isCrashingSignal = false; // wasn't sent by the kernel, so it's not really a crash
|
||||||
|
if (isCrashingSignal)
|
||||||
|
printCrashingSignalInfo(info);
|
||||||
|
else if (info && (info->si_code == SI_USER || info->si_code == SI_QUEUE))
|
||||||
|
printSentSignalInfo(info);
|
||||||
|
|
||||||
|
printTestRunTime();
|
||||||
if (signum != SIGINT) {
|
if (signum != SIGINT) {
|
||||||
generateStackTrace();
|
generateStackTrace();
|
||||||
if (pauseOnCrash) {
|
if (pauseOnCrash) {
|
||||||
@ -2089,9 +2125,6 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isCrashingSignal =
|
|
||||||
std::find(crashingSignals.begin(), crashingSignals.end(), signum) != crashingSignals.end();
|
|
||||||
|
|
||||||
// chain back to the previous handler, if any
|
// chain back to the previous handler, if any
|
||||||
for (size_t i = 0; i < fatalSignals.size(); ++i) {
|
for (size_t i = 0; i < fatalSignals.size(); ++i) {
|
||||||
struct sigaction &act = oldActions()[i];
|
struct sigaction &act = oldActions()[i];
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
********* Start testing of tst_Crashes *********
|
********* Start testing of tst_Crashes *********
|
||||||
Config: Using QtTest library @INSERT_QT_VERSION_HERE@, Qt @INSERT_QT_VERSION_HERE@
|
Config: Using QtTest library @INSERT_QT_VERSION_HERE@, Qt @INSERT_QT_VERSION_HERE@
|
||||||
PASS : tst_Crashes::initTestCase()
|
PASS : tst_Crashes::initTestCase()
|
||||||
QFATAL : tst_Crashes::crash() Received signal 11
|
Received signal 11 (SIGSEGV), code 1, for address 0x0000000000000004
|
||||||
Function time: ms Total time: ms
|
Function time: ms, total time: ms
|
||||||
FAIL! : tst_Crashes::crash() Received a fatal error.
|
|
||||||
Totals: 1 passed, 1 failed, 0 skipped, 0 blacklisted
|
|
||||||
********* Finished testing of tst_Crashes *********
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user