mirror of
https://github.com/golang/go
synced 2024-11-22 02:04:40 -07:00
libmach: fix new thread race with Linux
If you look at the sequence of values returned by waitpid, it simply tells us about the child of clone before it tells us that the parent called clone. There's nothing we can do but assume unexpected tids are newly cloned children. Tested with 6prof on godoc. Fixes #251. R=r CC=golang-dev https://golang.org/cl/2167045
This commit is contained in:
parent
ca9d3f3463
commit
323a116fd0
@ -202,6 +202,8 @@ attachthread(int pid, int tid, int *new, int newstate)
|
||||
memset(t, 0, sizeof *t);
|
||||
|
||||
thr[nthr++] = t;
|
||||
if(pid == 0 && nthr > 0)
|
||||
pid = thr[0]->pid;
|
||||
t->pid = pid;
|
||||
t->tid = tid;
|
||||
t->state = newstate;
|
||||
@ -296,7 +298,9 @@ wait1(int nohang)
|
||||
if(nohang != 0)
|
||||
nohang = WNOHANG;
|
||||
|
||||
status = 0;
|
||||
tid = waitpid(-1, &status, __WALL|WUNTRACED|WSTOPPED|WCONTINUED|nohang);
|
||||
|
||||
if(tid < 0)
|
||||
return -1;
|
||||
if(tid == 0)
|
||||
@ -305,12 +309,16 @@ wait1(int nohang)
|
||||
if(trace > 0 && status != NormalStop)
|
||||
fprint(2, "TID %d: %#x\n", tid, status);
|
||||
|
||||
// If we've not heard of this tid, something is wrong.
|
||||
t = findthread(tid);
|
||||
if(t == nil) {
|
||||
fprint(2, "ptrace waitpid: unexpected new tid %d status %#x\n", tid, status);
|
||||
// Sometimes the kernel tells us about new threads
|
||||
// before we see the parent clone.
|
||||
t = attachthread(0, tid, &new, Stopped);
|
||||
if(t == nil) {
|
||||
fprint(2, "failed to attach to new thread %d\n", tid);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(WIFSTOPPED(status)) {
|
||||
t->state = Stopped;
|
||||
@ -339,8 +347,6 @@ wait1(int nohang)
|
||||
}
|
||||
t->child = data;
|
||||
attachthread(t->pid, t->child, &new, Running);
|
||||
if(!new)
|
||||
fprint(2, "ptrace child: not new\n");
|
||||
break;
|
||||
|
||||
case PTRACE_EVENT_EXEC:
|
||||
|
Loading…
Reference in New Issue
Block a user