On 06/10/2013 04:55 PM, Dmitry V. Levin 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.
> * tests/detach: New test.
> * tests/Makefile.am (TESTS): Add it.
> 
> Reported-by: Raghavendra D Prabhu <[email protected]>
> ---
> Denys, please have a look whether this fix is correct.
> 
> --- a/strace.c
> +++ b/strace.c
> @@ -769,7 +769,15 @@ detach(struct tcb *tcp)
>                       if (errno != ESRCH)
>                               perror_msg("detach: checking sanity");
>               }
> -             else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
> +#if USE_SEIZE
> +             else if (!sigstop_expected && use_seize
> +                      && ptrace(PTRACE_INTERRUPT, tcp->pid, 0, 0) < 0) {
> +                     if (errno != ESRCH)
> +                             perror_msg("detach: ptrace(PTRACE_INTERRUPT, 
> ...)");
> +             }
> +#endif
> +             else if (!sigstop_expected && !use_seize
> +                      && my_tkill(tcp->pid, SIGSTOP) < 0) {
>                       if (errno != ESRCH)
>                               perror_msg("detach: stopping child");
>               }

The logic was:

                else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
                        if (errno != ESRCH)
                                perror_msg("detach: stopping child");
                }
                else
                        sigstop_expected = 1;

which, if my_tkill succeeded, was setting sigstop_expected = 1.

Now if we send PTRACE_INTERRUPT, we also set sigstop_expected = 1.

But there will be no SIGSTOP (unless tracee is already stopped, then yes) -
PTRACE_INTERRUPT generates SIGTRAP-stop!

I propose the attached patch.
Sorry, Thunderbird mangles inline patches :(
diff --git a/defs.h b/defs.h
index 3f07c4f..fbbe48c 100644
--- a/defs.h
+++ b/defs.h
@@ -227,16 +227,14 @@ extern long ptrace(int, int, char *, long);
 # define PTRACE_POKEUSER PTRACE_POKEUSR
 #endif
 
-#if USE_SEIZE
-# undef PTRACE_SEIZE
-# define PTRACE_SEIZE		0x4206
-# undef PTRACE_INTERRUPT
-# define PTRACE_INTERRUPT	0x4207
-# undef PTRACE_LISTEN
-# define PTRACE_LISTEN		0x4208
-# undef PTRACE_EVENT_STOP
-# define PTRACE_EVENT_STOP	128
-#endif
+#undef PTRACE_SEIZE
+#define PTRACE_SEIZE		0x4206
+#undef PTRACE_INTERRUPT
+#define PTRACE_INTERRUPT	0x4207
+#undef PTRACE_LISTEN
+#define PTRACE_LISTEN		0x4208
+#undef PTRACE_EVENT_STOP
+#define PTRACE_EVENT_STOP	128
 
 #ifdef ALPHA
 # define REG_R0 0
diff --git a/strace.c b/strace.c
index 6eab600..8f67022 100644
--- a/strace.c
+++ b/strace.c
@@ -724,7 +724,7 @@ droptcb(struct tcb *tcp)
 	memset(tcp, 0, sizeof(*tcp));
 }
 
-/* detach traced process; continue with sig
+/* Detach traced process.
  * Never call DETACH twice on the same process as both unattached and
  * attached-unstopped processes give the same ESRCH.  For unattached process we
  * would SIGSTOP it and wait for its SIGSTOP notification forever.
@@ -757,7 +757,7 @@ detach(struct tcb *tcp)
 		 * would be left stopped (process state T).
 		 */
 		sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
-		error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
+		error = ptrace(PTRACE_DETACH, tcp->pid, 0, 0);
 		if (error == 0) {
 			/* On a clear day, you can see forever. */
 		}
@@ -769,12 +769,21 @@ 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 (!sigstop_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 && errno != ESRCH) {
+				if (use_seize)
+					perror_msg("detach: ptrace(PTRACE_INTERRUPT, ...)");
+				else
+					perror_msg("detach: stopping child");
+			} else {
+				sigstop_expected = 1;
+			}
 		}
-		else
-			sigstop_expected = 1;
 	}
 
 	if (sigstop_expected) {
@@ -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;
 			}
@@ -2252,7 +2263,6 @@ trace(void)
 				goto restart_tracee;
 
 			/* It's group-stop */
-#if USE_SEIZE
 			if (use_seize) {
 				/*
 				 * This ends ptrace-stop, but does *not* end group-stop.
@@ -2266,7 +2276,6 @@ trace(void)
 				continue;
 			}
 			/* We don't have PTRACE_LISTEN support... */
-#endif
 			goto restart_tracee;
 		}
 
------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:

Build for Windows Store.

http://p.sf.net/sfu/windows-dev2dev
_______________________________________________
Strace-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to