diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2022-05-03 09:14:57 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2022-05-30 15:56:38 -0700 |
commit | 7ad8a2e8fe967a46127d3ba1f0ec5901921819fd (patch) | |
tree | 98d32ec6d5a892882b2a33737e3e5ed809f3425c /src/testlib/qtestcase.cpp | |
parent | d5f4f91c3c2e6b99b671fd4426a397247b7be4fe (diff) |
FatalSignalHandler: expand to more Unix OSes than just Linux and macOS
At least for my FreeBSD this makes sense. The default debugger search is
gdb first then lldb on Linux-not-Android and for QNX (qcc is GCC after
all), but lldb first everywhere else.
With LLVM14 from Ports, I get:
$ tests/auto/corelib/tools/qhashseed/tst_qhashseed | head -1
********* Start testing of tst_QHashSeed *********
Config: Using QtTest library 6.4.0, Qt 6.4.0 (x86_64-little_endian-lp64 shared (dynamic) debug build; by Clang 14.0.0), freebsd 13.0
=== Received signal at function time: 1ms, total time: 3ms, dumping stack ===
(lldb) process attach --pid 1782
Process 1782 stopped
Executable module set to "/usr/home/tjmaciei/obj/qt/qt6/qtbase/tests/auto/corelib/tools/qhashseed/tst_qhashseed".
Architecture set to: x86_64--freebsd13.0.
(lldb) bt all
* thread #1, name = 'tst_qhashseed'
* frame #0: 0x0000000800f227c8 libc.so.7`_wait4 at _wait4.S:4
frame #1: 0x00000008003243bc libthr.so.3`__thr_wait4(pid=<unavailable>, status=<unavailable>, options=<unavailable>, rusage=<unavailable>) at thr_syscalls.c:581:8
frame #2: 0x00000008002b9c73 libQt6Test.t.so.6`(anonymous namespace)::StackTraceHandler::generate() at qtestcase.cpp:393:9
[...]
=== End of stack trace ===
Received signal 13
Function time: 1ms Total time: 3ms
Support for Windows left as an exercise for later. The
WindowsFaultHandler code doesn't even call generateStackTrace().
Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16eba471f58ff3cb
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/testlib/qtestcase.cpp')
-rw-r--r-- | src/testlib/qtestcase.cpp | 60 |
1 files changed, 53 insertions, 7 deletions
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index b42ab6f5f9..bf742e6529 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -80,6 +80,9 @@ #include <QtCore/private/qcore_unix_p.h> #include <errno.h> +#if __has_include(<paths.h>) +# include <paths.h> +#endif #include <signal.h> #include <time.h> #include <sys/mman.h> @@ -89,6 +92,9 @@ # if !defined(Q_OS_INTEGRITY) # include <sys/resource.h> # endif +# ifndef _PATH_DEFPATH +# define _PATH_DEFPATH "/usr/bin:/bin" +# endif # ifndef SIGSTKSZ # define SIGSTKSZ 0 /* we have code to set the minimum */ # endif @@ -288,12 +294,52 @@ static void prepareStackTrace() return; // LLDB will fail to provide a valid stack trace #endif - // prepare the command to be run (our PID shouldn't change!) -# ifdef Q_OS_LINUX - debugger = Gdb; -# elif defined(Q_OS_MACOS) - debugger = Lldb; +#ifdef Q_OS_UNIX + // like QStandardPaths::findExecutable(), but simpler + auto hasExecutable = [](const char *execname) { + std::string candidate; + std::string path; + if (const char *p = getenv("PATH"); p && *p) + path = p; + else + path = _PATH_DEFPATH; + for (const char *p = std::strtok(&path[0], ":'"); p; p = std::strtok(nullptr, ":")) { + candidate = p; + candidate += '/'; + candidate += execname; + if (QT_ACCESS(candidate.data(), X_OK) == 0) + return true; + } + return false; + }; + + static constexpr DebuggerProgram debuggerSearchOrder[] = { +# if defined(Q_OS_QNX) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) + Gdb, Lldb +# else + Lldb, Gdb # endif + }; + for (DebuggerProgram candidate : debuggerSearchOrder) { + switch (candidate) { + case None: + Q_UNREACHABLE(); + break; + case Gdb: + if (hasExecutable("gdb")) { + debugger = Gdb; + return; + } + break; + case Lldb: + if (hasExecutable("lldb")) { + debugger = Lldb; + return; + } + break; + } + } +#endif // Q_OS_UNIX } [[maybe_unused]] static void generateStackTrace() @@ -301,7 +347,7 @@ static void prepareStackTrace() if (debugger == None || alreadyDebugging()) return; -#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS) +#if defined(Q_OS_UNIX) && !defined(Q_OS_WASM) && !defined(Q_OS_INTEGRITY) const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime()); const int msecsTotalTime = qRound(QTestLog::msecsTotalTime()); writeToStderr("\n=== Received signal at function time: ", asyncSafeToString(msecsFunctionTime), @@ -341,7 +387,7 @@ static void prepareStackTrace() EINTR_LOOP(ret, waitpid(pid, nullptr, 0)); } writeToStderr("=== End of stack trace ===\n"); -#endif +#endif // Q_OS_UNIX && !Q_OS_WASM } static bool installCoverageTool(const char * appname, const char * testname) |