summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchappedm@gmail.com <chappedm@gmail.com@6b5cf1ce-ec42-a296-1ba9-69fdba395a50>2012-11-03 14:52:42 +0000
committerchappedm@gmail.com <chappedm@gmail.com@6b5cf1ce-ec42-a296-1ba9-69fdba395a50>2012-11-03 14:52:42 +0000
commit5dd53ab6cbf9d98f2d60546835e84785a104da46 (patch)
treef8545b981f12c9e6406beb9af0fa5465f4ce6e4a
parent6c436203522156699ef11c6792ed481e02cef366 (diff)
downloadgperftools-5dd53ab6cbf9d98f2d60546835e84785a104da46.tar.gz
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
-rw-r--r--src/base/linuxthreads.cc40
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++;
}
}
}