pid_t tid = INTUSE(dwfl_thread_tid) (thread);
assert (pid_arg->tid_attached == tid);
pid_arg->tid_attached = 0;
- if (! pid_arg->stopped)
- {
- ptrace (PTRACE_DETACH, tid, NULL, NULL);
- return;
- }
+ // Older kernels (tested kernel-2.6.18-348.12.1.el5.x86_64) need special
+ // handling of the detachment to keep the process State: T (stopped).
- syscall (__NR_tkill, tid, SIGSTOP);
- ptrace (PTRACE_DETACH, tid, NULL, (void *) (intptr_t) SIGSTOP);
- // Wait till the SIGSTOP settles down.
- int i;
- for (i = 0; i < 100000; i++)
- if (linux_proc_pid_is_stopped (tid))
- break;
++ if (pid_arg->tid_was_stopped)
++ syscall (__NR_tkill, tid, SIGSTOP);
+ /* This handling is needed only on older Linux kernels such as
+ 2.6.32-358.23.2.el6.ppc64. Later kernels such as 3.11.7-200.fc19.x86_64
+ remember the T (stopped) state themselves and no longer need to pass
+ SIGSTOP during PTRACE_DETACH. */
+ ptrace (PTRACE_DETACH, tid, NULL,
+ (void *) (intptr_t) (pid_arg->tid_was_stopped ? SIGSTOP : 0));
++ if (pid_arg->tid_was_stopped)
++ {
++ // Wait till the SIGSTOP settles down.
++ int i;
++ for (i = 0; i < 100000; i++)
++ if (linux_proc_pid_is_stopped (tid))
++ break;
++ }
}
static const Dwfl_Thread_Callbacks pid_thread_callbacks =