1 diff -durN strace-4.4.orig/strace.c strace-4.4/strace.c
2 --- strace-4.4.orig/strace.c Fri Aug 3 13:43:35 2001
3 +++ strace-4.4/strace.c Thu Jul 4 10:41:55 2002
7 * Linux wrongly insists the child be stopped
8 - * before detaching. Arghh. We go through hoops
9 - * to make a clean break of things.
10 + * before detaching. This creates numerous headaches
11 + * as the process we are tracing may be running.
13 + * First try to simply detach from the process; if it was
14 + * already stopped, this will succeed and we're done.
16 + * Otherwise stop the process by sending it a SIGSTOP
19 + * Once the process is stopped we have to make sure it
20 + * received the SIGSTOP (it may have received a SIGTRAP or
21 + * other signal). If it did not receive the SIGSTOP,
22 + * restart the process and try again.
24 + * Once stopped with a SIGSTOP, we can detach from the
25 + * process via PTRACE_DETACH.
30 -#define PTRACE_DETACH PTRACE_SUNDETACH
33 if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
34 /* On a clear day, you can see forever. */
36 - else if (errno != ESRCH) {
37 - /* Shouldn't happen. */
38 - perror("detach: ptrace(PTRACE_DETACH, ...)");
40 - else if (kill(tcp->pid, 0) < 0) {
42 - perror("detach: checking sanity");
44 - else if (kill(tcp->pid, SIGSTOP) < 0) {
46 - perror("detach: stopping child");
52 - if (waitpid(tcp->pid, &status, 0) < 0) {
53 - if (errno != ECHILD)
54 + if (kill(tcp->pid, 0) < 0) {
56 + perror("detach: checking sanity");
58 + else if (kill(tcp->pid, SIGSTOP) < 0) {
60 + perror("detach: stopping child");
64 + * At this point the child should be stopped. Try to
65 + * wait on it so we can get its stop status. Use WNOHANG
66 + * to avoid this wait hanging.
68 + if (waitpid (tcp->pid, &status, (WUNTRACED | WNOHANG)) < 0) {
69 + if (errno != ECHILD) {
70 perror("detach: waiting");
75 + * Try again, this time with the __WCLONE
76 + * flag. Note we may get notifications
77 + * for other processes/threads!
83 + x = waitpid (-1, &status, __WCLONE);
84 + if (x == tcp->pid || x < 0 || errno != 0)
90 + perror ("Unable to wait on inferior");
96 + * At this point we have wait status for the
97 + * inferior. If it did not stop, then all
100 if (!WIFSTOPPED(status)) {
101 /* Au revoir, mon ami. */
106 + * If the process/thread has stopped with a
107 + * SIGSTOP, then we can continue and detach
108 + * with PTRACE_DETACH.
110 if (WSTOPSIG(status) == SIGSTOP) {
111 if ((error = ptrace(PTRACE_DETACH,
112 - tcp->pid, (char *) 1, sig)) < 0) {
113 + tcp->pid, (char *) 1, sig)) < 0) {
115 perror("detach: ptrace(PTRACE_DETACH, ...)");
122 + * The process/thread did not stop with a SIGSTOP,
123 + * so let it continue and try again to stop it with
126 if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
127 - WSTOPSIG(status) == SIGTRAP ?
128 - 0 : WSTOPSIG(status))) < 0) {
129 + WSTOPSIG(status) == SIGTRAP ?
130 + 0 : WSTOPSIG(status))) < 0) {
132 perror("detach: ptrace(PTRACE_CONT, ...)");
141 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */