+2013-12-02 Jan Kratochvil <jan.kratochvil@redhat.com>
+
+ 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 <jan.kratochvil@redhat.com>
* Makefile.am (check_PROGRAMS): Add backtrace, backtrace-child,
#include <fcntl.h>
#include <string.h>
#include <argp.h>
+#include <sys/syscall.h>
#include ELFUTILS_HEADER(dwfl)
static int
#include <unistd.h>
#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