From 5dd53ab6cbf9d98f2d60546835e84785a104da46 Mon Sep 17 00:00:00 2001 From: "chappedm@gmail.com" Date: Sat, 3 Nov 2012 14:52:42 +0000 Subject: [PATCH] issue-481: Replaced test mechanism for distinct address spaces with a more reliable mechanism Rather than using sys_ptrace+PTRACE_PEEK_DATA to determine whether address spaces are distinct, we now use sys_waitpid+__WCLONE. See issue-481 for a more detailed rationale. git-svn-id: http://gperftools.googlecode.com/svn/trunk@167 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 --- src/base/linuxthreads.cc | 40 ++++++++++++++++++++-------------------- 1 file 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++; } } }