From 7bf10474b981aa27f6b8c5b5e3f563d21f2eafca Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Mon, 16 Dec 2002 20:42:50 +0000 Subject: [PATCH] Fix botched commit. --- strace.c | 106 ++++++++++++++----------------------------------------- 1 file changed, 27 insertions(+), 79 deletions(-) diff --git a/strace.c b/strace.c index ea9439bb..ec8d7527 100644 --- a/strace.c +++ b/strace.c @@ -1042,110 +1042,58 @@ int sig; #ifdef LINUX /* * Linux wrongly insists the child be stopped - * before detaching. This creates numerous headaches - * as the process we are tracing may be running. - * - * First try to simply detach from the process; if it was - * already stopped, this will succeed and we're done. - * - * Otherwise stop the process by sending it a SIGSTOP - * signal. - * - * Once the process is stopped we have to make sure it - * received the SIGSTOP (it may have received a SIGTRAP or - * other signal). If it did not receive the SIGSTOP, - * restart the process and try again. - * - * Once stopped with a SIGSTOP, we can detach from the - * process via PTRACE_DETACH. - * + * before detaching. Arghh. We go through hoops + * to make a clean break of things. */ - +#if defined(SPARC) +#undef PTRACE_DETACH +#define PTRACE_DETACH PTRACE_SUNDETACH +#endif if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) { /* On a clear day, you can see forever. */ - } else { - + } + else if (errno != ESRCH) { + /* Shouldn't happen. */ + perror("detach: ptrace(PTRACE_DETACH, ...)"); + } + else if (kill(tcp->pid, 0) < 0) { + if (errno != ESRCH) + perror("detach: checking sanity"); + } + else if (kill(tcp->pid, SIGSTOP) < 0) { + if (errno != ESRCH) + perror("detach: stopping child"); + } + else { for (;;) { - if (kill(tcp->pid, 0) < 0) { - if (errno != ESRCH) - perror("detach: checking sanity"); - } - else if (kill(tcp->pid, SIGSTOP) < 0) { - if (errno != ESRCH) - perror("detach: stopping child"); - } - - /* - * At this point the child should be stopped. Try to - * wait on it so we can get its stop status. Use WNOHANG - * to avoid this wait hanging. - */ - if (waitpid (tcp->pid, &status, (WUNTRACED | WNOHANG)) < 0) { - if (errno != ECHILD) { + if (waitpid(tcp->pid, &status, 0) < 0) { + if (errno != ECHILD) perror("detach: waiting"); - } else { - - /* - * Try again, this time with the __WCLONE - * flag. Note we may get notifications - * for other processes/threads! - */ - errno = 0; - while (1) { - int x; - - x = waitpid (-1, &status, __WCLONE); - if (x == tcp->pid || x < 0 || errno != 0) - break; - } - } - - if (errno) { - perror ("Unable to wait on inferior"); - return -1; - } + break; } - - /* - * At this point we have wait status for the - * inferior. If it did not stop, then all - * bets are off. - */ if (!WIFSTOPPED(status)) { /* Au revoir, mon ami. */ break; } - - /* - * If the process/thread has stopped with a - * SIGSTOP, then we can continue and detach - * with PTRACE_DETACH. - */ if (WSTOPSIG(status) == SIGSTOP) { if ((error = ptrace(PTRACE_DETACH, - tcp->pid, (char *) 1, sig)) < 0) { + tcp->pid, (char *) 1, sig)) < 0) { if (errno != ESRCH) perror("detach: ptrace(PTRACE_DETACH, ...)"); /* I died trying. */ } break; } - - /* - * The process/thread did not stop with a SIGSTOP, - * so let it continue and try again to stop it with - * a SIGSTOP. - */ if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1, - WSTOPSIG(status) == SIGTRAP ? - 0 : WSTOPSIG(status))) < 0) { + WSTOPSIG(status) == SIGTRAP ? + 0 : WSTOPSIG(status))) < 0) { if (errno != ESRCH) perror("detach: ptrace(PTRACE_CONT, ...)"); break; } } } -#endif +#endif /* LINUX */ #if defined(SUNOS4) /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */ -- 2.40.0