On Tue, Jun 18, 2013 at 06:18:14PM +0200, Denys Vlasenko wrote: > * strace.c (detach) [USE_SEIZE]: If PTRACE_SEIZE API is in use, stop > the tracee using PTRACE_INTERRUPT instead of sending it a SIGSTOP. > In a subsequent waitpid loop, wait for either SIGSTOP or SIGTRAP. > > Signed-off-by: Denys Vlasenko <dvlas...@redhat.com> > --- > strace.c | 33 ++++++++++++++++++++++----------- > 1 file changed, 22 insertions(+), 11 deletions(-) > > diff --git a/strace.c b/strace.c > index 87aad48..af8156d 100644 > --- a/strace.c > +++ b/strace.c > @@ -733,7 +733,7 @@ static int > detach(struct tcb *tcp) > { > int error; > - int status, sigstop_expected; > + int status, stop_expected; > > if (tcp->flags & TCB_BPTSET) > clearbpt(tcp); > @@ -749,15 +749,15 @@ detach(struct tcb *tcp) > #endif > > error = 0; > - sigstop_expected = 0; > + stop_expected = 0; > if (tcp->flags & TCB_ATTACHED) { > /* > * We attached but possibly didn't see the expected SIGSTOP. > * We must catch exactly one as otherwise the detached process > * would be left stopped (process state T). > */ > - sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP); > - error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0); > + stop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP); > + error = ptrace(PTRACE_DETACH, tcp->pid, 0, 0); > if (error == 0) { > /* On a clear day, you can see forever. */ > } > @@ -769,15 +769,24 @@ detach(struct tcb *tcp) > if (errno != ESRCH) > perror_msg("detach: checking sanity"); > } > - else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) { > - if (errno != ESRCH) > - perror_msg("detach: stopping child"); > + else if (!stop_expected) { > + /* Process is running, need to stop it first */ > + if (use_seize) > + error = ptrace(PTRACE_INTERRUPT, tcp->pid, 0, > 0); > + else > + error = my_tkill(tcp->pid, SIGSTOP); > + if (!error) > + stop_expected = 1; > + else if (errno != ESRCH) { > + if (use_seize) > + perror_msg("detach: > ptrace(PTRACE_INTERRUPT, ...)"); > + else > + perror_msg("detach: stopping child"); > + } > } > - else > - sigstop_expected = 1; > } > > - if (sigstop_expected) { > + if (stop_expected) { > for (;;) { > #ifdef __WALL > if (waitpid(tcp->pid, &status, __WALL) < 0) { > @@ -810,7 +819,9 @@ detach(struct tcb *tcp) > /* Au revoir, mon ami. */ > break; > } > - if (WSTOPSIG(status) == SIGSTOP) { > + if (WSTOPSIG(status) == SIGSTOP > + || WSTOPSIG(status) == SIGTRAP /* may be generated by > PTRACE_INTERRUPT stop */ > + ) {
In case of PTRACE_INTERRUPT this WSTOPSIG(status) is not plain SIGTRAP but (SIGTRAP | 0x80), which also may happen in other !use_seize cases. That is, the right check seems to be WSTOPSIG(status) == SIGSTOP || (use_seize && WSTOPSIG(status) == (SIGTRAP | 0x80)) It also passes both tests/detach-sleeping and tests/detach-stopped. -- ldv
pgpPo6bglE0t9.pgp
Description: PGP signature
------------------------------------------------------------------------------ This SF.net email is sponsored by Windows: Build for Windows Store. http://p.sf.net/sfu/windows-dev2dev
_______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel