]> granicus.if.org Git - strace/commitdiff
Attach to the target process before attempting to attach to its siblings
authorDmitry V. Levin <ldv@altlinux.org>
Mon, 25 Jul 2016 18:48:50 +0000 (18:48 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Fri, 29 Jul 2016 17:14:28 +0000 (17:14 +0000)
* strace.c (attach_tcb): Attach to tcp->pid first.

strace.c

index 185d669fbe891fdec8141a828638b685be712d0a..2e2d4b5ec2a381597eee76cba91c67697ef0b1f4 100644 (file)
--- a/strace.c
+++ b/strace.c
@@ -1017,71 +1017,6 @@ process_opt_p_list(char *opt)
 static void
 attach_tcb(struct tcb *const tcp)
 {
-       if (followfork && tcp->pid != strace_child) {
-               char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
-               sprintf(procdir, "/proc/%d/task", tcp->pid);
-
-               DIR *dir = opendir(procdir);
-               if (dir != NULL) {
-                       unsigned int ntid = 0, nerr = 0;
-                       struct_dirent *de;
-
-                       while ((de = read_dir(dir)) != NULL) {
-                               if (de->d_fileno == 0)
-                                       continue;
-
-                               int tid = string_to_uint(de->d_name);
-                               if (tid <= 0)
-                                       continue;
-
-                               ++ntid;
-                               if (ptrace_attach_or_seize(tid) < 0) {
-                                       ++nerr;
-                                       if (debug_flag)
-                                               perror_msg("attach: ptrace(%s, %d)",
-                                                          ptrace_attach_cmd, tid);
-                                       continue;
-                               }
-                               if (debug_flag)
-                                       error_msg("attach to pid %d succeeded", tid);
-
-                               struct tcb *tid_tcp =
-                                       (tid == tcp->pid) ? tcp : alloctcb(tid);
-                               tid_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
-                               newoutf(tid_tcp);
-                       }
-
-                       closedir(dir);
-
-                       ntid -= nerr;
-                       if (ntid == 0) {
-                               perror_msg("attach: ptrace(PTRACE_ATTACH, ...)");
-                               droptcb(tcp);
-                               return;
-                       }
-
-                       if (!qflag) {
-                               if (ntid > 1)
-                                       error_msg("Process %u attached"
-                                                 " with %u threads",
-                                                 tcp->pid, ntid);
-                               else
-                                       error_msg("Process %u attached",
-                                                 tcp->pid);
-                       }
-
-                       if (!(tcp->flags & TCB_ATTACHED)) {
-                               /* -p PID, we failed to attach to PID itself
-                                * but did attach to some of its sibling threads.
-                                * Drop PID's tcp.
-                                */
-                               droptcb(tcp);
-                       }
-
-                       return;
-               } /* if (opendir worked) */
-       } /* if (-f) */
-
        if (ptrace_attach_or_seize(tcp->pid) < 0) {
                perror_msg("attach: ptrace(%s, %d)",
                           ptrace_attach_cmd, tcp->pid);
@@ -1094,8 +1029,52 @@ attach_tcb(struct tcb *const tcp)
        if (debug_flag)
                error_msg("attach to pid %d (main) succeeded", tcp->pid);
 
-       if (!qflag)
-               error_msg("Process %u attached", tcp->pid);
+       char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
+       DIR *dir;
+       unsigned int ntid = 0, nerr = 0;
+
+       if (followfork && tcp->pid != strace_child &&
+           sprintf(procdir, "/proc/%d/task", tcp->pid) > 0 &&
+           (dir = opendir(procdir)) != NULL) {
+               struct_dirent *de;
+
+               while ((de = read_dir(dir)) != NULL) {
+                       if (de->d_fileno == 0)
+                               continue;
+
+                       int tid = string_to_uint(de->d_name);
+                       if (tid <= 0 || tid == tcp->pid)
+                               continue;
+
+                       ++ntid;
+                       if (ptrace_attach_or_seize(tid) < 0) {
+                               ++nerr;
+                               if (debug_flag)
+                                       perror_msg("attach: ptrace(%s, %d)",
+                                                  ptrace_attach_cmd, tid);
+                               continue;
+                       }
+                       if (debug_flag)
+                               error_msg("attach to pid %d succeeded", tid);
+
+                       struct tcb *tid_tcp = alloctcb(tid);
+                       tid_tcp->flags |= TCB_ATTACHED | TCB_STARTUP |
+                                         post_attach_sigstop;
+                       newoutf(tid_tcp);
+               }
+
+               closedir(dir);
+       }
+
+       if (!qflag) {
+               if (ntid > nerr)
+                       error_msg("Process %u attached"
+                                 " with %u threads",
+                                 tcp->pid, ntid - nerr + 1);
+               else
+                       error_msg("Process %u attached",
+                                 tcp->pid);
+       }
 }
 
 static void