diff options
Diffstat (limited to 'process.c')
-rw-r--r-- | process.c | 20 |
1 files changed, 12 insertions, 8 deletions
@@ -26,7 +26,7 @@ find_process(pid_t pid) struct process * -add_process(pid_t pid, unsigned long int trace_options) +add_process(pid_t pid, pid_t leader, unsigned long int trace_options) { struct process *proc; int status, sig; @@ -35,12 +35,16 @@ add_process(pid_t pid, unsigned long int trace_options) if (!proc) eprintf("calloc: %s\n"); proc->pid = pid; + proc->thread_leader = leader; proc->next = &tail; proc->prev = tail.prev; proc->prev->next = proc; tail.prev = proc; - while (waitpid(pid, &status, WSTOPPED) != pid) { + if (!leader) + leader = pid; + + while (waitpid(pid, &status, WUNTRACED) != pid) { if (errno == EINTR) continue; eprintf_and_kill(pid, "waitpid %ju <buffer> WSTOPPED:", (uintmax_t)pid); @@ -48,15 +52,15 @@ add_process(pid_t pid, unsigned long int trace_options) sig = WIFSTOPPED(status) ? WSTOPSIG(status) : 0; if (sig == SIGSTOP) { - if (ptrace(PTRACE_SEIZE, pid, 0, trace_options)) - eprintf_and_kill(pid, "ptrace PTRACE_SEIZE %ju 0 ...:", (uintmax_t)pid); + if (ptrace(PTRACE_SEIZE, pid, NULL, trace_options)) + eprintf_and_kill(pid, "ptrace PTRACE_SEIZE %ju NULL ...:", (uintmax_t)pid); if (ptrace(PTRACE_INTERRUPT, pid, NULL, 0)) eprintf_and_kill(pid, "ptrace PTRACE_INTERRUPT %ju NULL 0:", (uintmax_t)pid); - if (kill(pid, SIGCONT) < 0) - eprintf_and_kill(pid, "kill &ju SIGCONT:", (uintmax_t)pid); + if (tgkill(leader, pid, SIGCONT) < 0) + eprintf_and_kill(pid, "tgkill %ju %ju SIGCONT:", (uintmax_t)leader, (uintmax_t)pid); } else if (sig == SIGTRAP && status & PTRACE_EVENT_STOP << 16) { - if (ptrace(PTRACE_SYSCALL, pid, NULL, 0)) - eprintf_and_kill(pid, "ptrace PTRACE_SYSCALL %ju NULL 0:", (uintmax_t)pid); + if (ptrace(PTRACE_SETOPTIONS, pid, NULL, trace_options)) + eprintf_and_kill(pid, "ptrace PTRACE_SETOPTIONS %ju NULL ...:", (uintmax_t)pid); } else { eprintf_and_kill(pid, "unexpected return of waitpid %ju <buffer> WSTOPPED: %#x\n", (uintmax_t)pid, status); } |