diff options
-rw-r--r-- | src/base/linuxthreads.cc | 40 |
1 files changed, 20 insertions, 20 deletions
diff --git a/src/base/linuxthreads.cc b/src/base/linuxthreads.cc index 9d144ef..1f8d4c3 100644 --- a/src/base/linuxthreads.cc +++ b/src/base/linuxthreads.cc @@ -408,7 +408,7 @@ static void ListerThread(struct ListerParams *args) { /* Check if the marker is identical to the one we created */ if (sys_stat(fname, &tmp_sb) >= 0 && marker_sb.st_ino == tmp_sb.st_ino) { - long i, j; + long i; /* Found one of our threads, make sure it is no duplicate */ for (i = 0; i < num_threads; i++) { @@ -444,28 +444,28 @@ static void ListerThread(struct ListerParams *args) { sig_num_threads = num_threads; goto next_entry; } - while (sys_waitpid(pid, (int *)0, __WALL) < 0) { + /* Attaching to a process doesn't guarantee it'll stop before + * ptrace returns; you have to wait on it. Specifying __WCLONE + * means it will only wait for clone children (i.e. threads, + * not processes). + */ + while (sys_waitpid(pid, (int *)0, __WCLONE) < 0) { if (errno != EINTR) { - sys_ptrace_detach(pid); - num_threads--; - sig_num_threads = num_threads; - goto next_entry; + /* Assumes ECHILD */ + if (pid == ppid) { + /* The parent is not a clone */ + found_parent = true; + break; + } else { + sys_ptrace_detach(pid); + num_threads--; + sig_num_threads = num_threads; + goto next_entry; + } } } - - if (sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i++ != j || - sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i != j) { - /* Address spaces are distinct, even though both - * processes show the "marker". This is probably - * a forked child process rather than a thread. - */ - sys_ptrace_detach(pid); - num_threads--; - sig_num_threads = num_threads; - } else { - found_parent |= pid == ppid; - added_entries++; - } + + added_entries++; } } } |