Test failed at utils_snprintf_abort_neg_size because pwtest think it's in a debugger
The logic here is that tests would run without fork() and signal catching if pwtest is attached with a debugger or running on valgrind, and abort() in tests will fall out causing the test failed.
But there is a problem on its debugger detection function is_debugger_attached()
, it says a debugger is attached even that is false for a particular situation that ptrace(PTRACE_ATTACH, ppid, NULL, 0)
returns -1 with errno
set to EPERM
because caller process requires CAP_SYS_PTRACE
permission to tracing non-descendant process. See "/proc/sys/kernel/yama/ptrace_scope" section in PTRACE(2).
The way is_debugger_attached()
detect is that it fork()
a child process which calls ptrace(PTRACE_ATTACH, ppid, NULL, 0)
on current process, and is_debugger_attached()
will eventually returns true
to indicate debugger is attached if the call returns a non-zero value (EPERM) suggesting a the process may already be being traced. See "ERRORS" section in PTRACE(2).
So if ptrace returns -1 with errno
set to EPERM
, it could be both missing permission or debugger already attached.
We can fix it by declare a PID that is allowed to perform PTRACE_TRACE on target using prctl()
.
Here is an attempt to fix it. (click to open)
diff --git a/test/pwtest.c b/test/pwtest.c
index 14b0954a..8fb950bf 100644
--- a/test/pwtest.c
+++ b/test/pwtest.c
@@ -47,6 +47,10 @@
#include <sys/wait.h>
#include <time.h>
+#if defined(__linux__)
+#include <sys/prctl.h>
+#endif
+
#include <valgrind/valgrind.h>
#include "spa/utils/ansi.h"
@@ -1139,6 +1143,9 @@ static bool is_debugger_attached(void)
return 0;
if (pid == 0) {
+ /* Wait till PR_SET_PTRACER is applied.
+ * Should use something like sigsuspend() instead */
+ usleep(200);
int ppid = getppid();
if (ptrace(PTRACE_ATTACH, ppid, NULL, 0) == 0) {
waitpid(ppid, NULL, 0);
@@ -1150,10 +1157,15 @@ static bool is_debugger_attached(void)
}
_exit(rc);
} else {
+#if defined(__linux__)
+ prctl(PR_SET_PTRACER, pid);
+#endif
waitpid(pid, &status, 0);
rc = WEXITSTATUS(status);
}
+ fprintf(stderr, "[Debug] is_debugger_attached %d\n", rc);
+
return !!rc;
}
But for best compatibility, I would propose to remove is_debugger_attached
completely. It's only meant to disable fork and monitoring on debugger environment to have abortion been caught, and we already have --no-fork
command line option for that, so why don't use --no-fork
instead.
cc @whot
edit: Oops, this duplicates #1285 (closed), I will close this once #1285 (closed) is solved.