]> git.pld-linux.org Git - packages/strace.git/blob - strace-threads.patch
- release 4
[packages/strace.git] / strace-threads.patch
1 diff -durN strace-4.4.orig/strace.c strace-4.4/strace.c
2 --- strace-4.4.orig/strace.c    Fri Aug  3 13:43:35 2001
3 +++ strace-4.4/strace.c Thu Jul  4 10:41:55 2002
4 @@ -993,58 +993,110 @@
5  #ifdef LINUX
6         /*
7          * Linux wrongly insists the child be stopped
8 -        * before detaching.  Arghh.  We go through hoops
9 -        * to make a clean break of things.
10 +        * before detaching.  This creates numerous headaches
11 +        * as the process we are tracing may be running.
12 +        *
13 +        * First try to simply detach from the process; if it was
14 +        * already stopped, this will succeed and we're done.
15 +        *
16 +        * Otherwise stop the process by sending it a SIGSTOP
17 +        * signal.
18 +        *
19 +        * Once the process is stopped we have to make sure it
20 +        * received the SIGSTOP (it may have received a SIGTRAP or
21 +        * other signal).  If it did not receive the SIGSTOP, 
22 +        * restart the process and try again. 
23 +        *
24 +        * Once stopped with a SIGSTOP, we can detach from the
25 +        * process via PTRACE_DETACH. 
26 +        *
27          */
28 -#if defined(SPARC)
29 -#undef PTRACE_DETACH
30 -#define PTRACE_DETACH PTRACE_SUNDETACH
31 -#endif
32 +       
33         if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
34                 /* On a clear day, you can see forever. */
35 -       }
36 -       else if (errno != ESRCH) {
37 -               /* Shouldn't happen. */
38 -               perror("detach: ptrace(PTRACE_DETACH, ...)");
39 -       }
40 -       else if (kill(tcp->pid, 0) < 0) {
41 -               if (errno != ESRCH)
42 -                       perror("detach: checking sanity");
43 -       }
44 -       else if (kill(tcp->pid, SIGSTOP) < 0) {
45 -               if (errno != ESRCH)
46 -                       perror("detach: stopping child");
47 -       }
48 -       else {
49 +       } else {
50 +
51                 for (;;) {
52 -                       if (waitpid(tcp->pid, &status, 0) < 0) {
53 -                               if (errno != ECHILD)
54 +                       if (kill(tcp->pid, 0) < 0) {
55 +                               if (errno != ESRCH)
56 +                                       perror("detach: checking sanity");
57 +                       }
58 +                       else if (kill(tcp->pid, SIGSTOP) < 0) {
59 +                               if (errno != ESRCH)
60 +                               perror("detach: stopping child");
61 +                       }
62 +       
63 +                       /*
64 +                       * At this point the child should be stopped.  Try to
65 +                       * wait on it so we can get its stop status.  Use WNOHANG
66 +                       * to avoid this wait hanging.
67 +                       */
68 +                       if (waitpid (tcp->pid, &status, (WUNTRACED | WNOHANG)) < 0) {
69 +                               if (errno != ECHILD) {
70                                         perror("detach: waiting");
71 -                               break;
72 +                               } else {
73 +       
74 +                                       /*
75 +                                       * Try again, this time with the __WCLONE
76 +                                       * flag.  Note we may get notifications
77 +                                       * for other processes/threads!
78 +                                       */
79 +                                       errno = 0;
80 +                                       while (1) {
81 +                                               int x;
82 +
83 +                                               x = waitpid (-1, &status, __WCLONE);
84 +                                               if (x == tcp->pid || x < 0 || errno != 0)
85 +                                                       break;
86 +                                       }
87 +                               }
88 +       
89 +                               if (errno) {
90 +                                       perror ("Unable to wait on inferior");
91 +                                       return -1;
92 +                               }
93                         }
94 +                       
95 +                       /*
96 +                       * At this point we have wait status for the
97 +                       * inferior.  If it did not stop, then all 
98 +                       * bets are off.
99 +                       */
100                         if (!WIFSTOPPED(status)) {
101                                 /* Au revoir, mon ami. */
102                                 break;
103                         }
104 +       
105 +                       /*
106 +                       * If the process/thread has stopped with a
107 +                       * SIGSTOP, then we can continue and detach
108 +                       * with PTRACE_DETACH.
109 +                       */
110                         if (WSTOPSIG(status) == SIGSTOP) {
111                                 if ((error = ptrace(PTRACE_DETACH,
112 -                                   tcp->pid, (char *) 1, sig)) < 0) {
113 +                               tcp->pid, (char *) 1, sig)) < 0) {
114                                         if (errno != ESRCH)
115                                                 perror("detach: ptrace(PTRACE_DETACH, ...)");
116                                         /* I died trying. */
117                                 }
118                                 break;
119                         }
120 +       
121 +                       /*
122 +                       * The process/thread did not stop with a SIGSTOP,
123 +                       * so let it continue and try again to stop it with
124 +                       * a SIGSTOP.
125 +                       */
126                         if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
127 -                           WSTOPSIG(status) == SIGTRAP ?
128 -                           0 : WSTOPSIG(status))) < 0) {
129 +                       WSTOPSIG(status) == SIGTRAP ?
130 +                       0 : WSTOPSIG(status))) < 0) {
131                                 if (errno != ESRCH)
132                                         perror("detach: ptrace(PTRACE_CONT, ...)");
133                                 break;
134                         }
135                 }
136         }
137 -#endif /* LINUX */
138 +#endif
139  
140  #if defined(SUNOS4)
141         /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
This page took 0.446625 seconds and 3 git commands to generate.