summaryrefslogtreecommitdiffstats
path: root/src/testlib/qtestcrashhandler_unix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/testlib/qtestcrashhandler_unix.cpp')
-rw-r--r--src/testlib/qtestcrashhandler_unix.cpp67
1 files changed, 56 insertions, 11 deletions
diff --git a/src/testlib/qtestcrashhandler_unix.cpp b/src/testlib/qtestcrashhandler_unix.cpp
index f0ffe36dd66..86a77312ba4 100644
--- a/src/testlib/qtestcrashhandler_unix.cpp
+++ b/src/testlib/qtestcrashhandler_unix.cpp
@@ -68,21 +68,36 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
-namespace QTest {
-namespace CrashHandler {
-struct iovec IoVec(struct iovec vec)
+template <typename... Args> static ssize_t writeToStderr(Args &&... args)
{
- return vec;
+ auto makeIovec = [](auto &&arg) {
+ if constexpr (std::is_same_v<std::decay_t<decltype(arg)>, iovec>) {
+ return arg;
+ } else {
+ struct iovec r = {};
+ r.iov_base = const_cast<char *>(arg);
+ r.iov_len = strlen(arg);
+ return r;
+ }
+ };
+ struct iovec vec[] = { makeIovec(std::forward<Args>(args))... };
+ return ::writev(STDERR_FILENO, vec, std::size(vec));
}
-struct iovec IoVec(const char *str)
+
+namespace {
+// async-signal-safe conversion from int to string
+struct AsyncSafeIntBuffer
{
- struct iovec r = {};
- r.iov_base = const_cast<char *>(str);
- r.iov_len = strlen(str);
- return r;
-}
+ // digits10 + 1 for all possible digits
+ // +1 for the sign
+ // +1 for the terminating null
+ static constexpr int Digits10 = std::numeric_limits<int>::digits10 + 3;
+ std::array<char, Digits10> array;
+ constexpr AsyncSafeIntBuffer() : array{} {} // initializes array
+ AsyncSafeIntBuffer(Qt::Initialization) {} // leaves array uninitialized
+};
-struct iovec asyncSafeToString(int n, AsyncSafeIntBuffer &&result)
+struct iovec asyncSafeToString(int n, AsyncSafeIntBuffer &&result = Qt::Uninitialized)
{
char *ptr = result.array.data();
if (false) {
@@ -127,7 +142,10 @@ struct iovec asyncSafeToString(int n, AsyncSafeIntBuffer &&result)
r.iov_len = ptr - result.array.data();
return r;
};
+} // unnamed namespace
+namespace QTest {
+namespace CrashHandler {
bool alreadyDebugging()
{
#if defined(Q_OS_LINUX)
@@ -349,6 +367,33 @@ void blockUnixSignals()
pthread_sigmask(SIG_BLOCK, &set, nullptr);
}
+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));
+}
+[[maybe_unused]] 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)));
+}
+[[maybe_unused]] static void printCrashingSignalInfo(...) {}
+
bool FatalSignalHandler::pauseOnCrash = false;
FatalSignalHandler::FatalSignalHandler()