From: Jan Kratochvil Date: Mon, 2 Dec 2013 20:52:26 +0000 (+0100) Subject: Handle T-stopped detach for old kernels X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f9244923462a0e5df3eb6e1f0bb2bf1f1df7bc2b;p=thirdparty%2Felfutils.git Handle T-stopped detach for old kernels Signed-off-by: Jan Kratochvil --- diff --git a/tests/ChangeLog b/tests/ChangeLog index af0e1c3d5..ba6dab241 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,10 @@ +2013-12-02 Jan Kratochvil + + Handle T-stopped detach for old kernels. + * backtrace.c: Include sys/syscall.h. + (linux_proc_pid_is_stopped): New function. + (ptrace_detach_stopped): Handle old kernels. + 2013-12-02 Jan Kratochvil * Makefile.am (check_PROGRAMS): Add backtrace, backtrace-child, diff --git a/tests/backtrace.c b/tests/backtrace.c index 06d387821..68ad95d61 100644 --- a/tests/backtrace.c +++ b/tests/backtrace.c @@ -36,6 +36,7 @@ #include #include #include +#include #include ELFUTILS_HEADER(dwfl) static int @@ -253,13 +254,43 @@ prepare_thread (pid_t pid2 __attribute__ ((unused)), #include #define tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig)) +static bool +linux_proc_pid_is_stopped (pid_t pid) +{ + char buffer[64]; + FILE *procfile; + bool retval, have_state; + + snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid); + procfile = fopen (buffer, "r"); + if (procfile == NULL) + return false; + + have_state = false; + while (fgets (buffer, sizeof (buffer), procfile) != NULL) + if (strncmp (buffer, "State:", 6) == 0) + { + have_state = true; + break; + } + retval = (have_state && strstr (buffer, "T (stopped)") != NULL); + fclose (procfile); + return retval; +} + static void ptrace_detach_stopped (pid_t pid) { + syscall (__NR_tkill, pid, SIGSTOP); errno = 0; long l = ptrace (PTRACE_DETACH, pid, NULL, (void *) (intptr_t) SIGSTOP); assert_perror (errno); assert (l == 0); + // Wait till the SIGSTOP settles down. + int i; + for (i = 0; i < 100000; i++) + if (linux_proc_pid_is_stopped (pid)) + break; } static void