[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