]> git.pld-linux.org Git - packages/strace.git/commitdiff
- based on two patches from rawhide. Makes strace work with clone()'d threads.
authorJacek Konieczny <jajcus@pld-linux.org>
Thu, 4 Jul 2002 08:53:49 +0000 (08:53 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    strace-threads.patch -> 1.1

strace-threads.patch [new file with mode: 0644]

diff --git a/strace-threads.patch b/strace-threads.patch
new file mode 100644 (file)
index 0000000..8609e6e
--- /dev/null
@@ -0,0 +1,141 @@
+diff -durN strace-4.4.orig/strace.c strace-4.4/strace.c
+--- strace-4.4.orig/strace.c   Fri Aug  3 13:43:35 2001
++++ strace-4.4/strace.c        Thu Jul  4 10:41:55 2002
+@@ -993,58 +993,110 @@
+ #ifdef LINUX
+       /*
+        * Linux wrongly insists the child be stopped
+-       * before detaching.  Arghh.  We go through hoops
+-       * to make a clean break of things.
++       * 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. 
++       *
+        */
+-#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 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 {
++      } else {
++
+               for (;;) {
+-                      if (waitpid(tcp->pid, &status, 0) < 0) {
+-                              if (errno != ECHILD)
++                      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) {
+                                       perror("detach: waiting");
+-                              break;
++                              } 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;
++                              }
+                       }
++                      
++                      /*
++                      * 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 /* LINUX */
++#endif
+ #if defined(SUNOS4)
+       /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
This page took 0.232795 seconds and 4 git commands to generate.