[PATCH] USE_SEIZE: fix detaching from stopped processes
Denys Vlasenko
dvlasenk at redhat.com
Tue Jun 18 16:18:14 UTC 2013
* 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 <dvlasenk at 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 */
+ ) {
ptrace_restart(PTRACE_DETACH, tcp, 0);
break;
}
--
1.8.1.4
More information about the Strace-devel
mailing list