mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/gc: do not race instrument syscall.forkAndExecInChild
Race instrumentation can allocate, switch stacks, preempt, etc. All that is not allowed in between fork and exec. Fixes #4840. R=golang-dev, daniel.morsing, dave CC=golang-dev https://golang.org/cl/11324044
This commit is contained in:
parent
7e270cf6c4
commit
63e0ddc7bf
3 changed files with 15 additions and 1 deletions
|
|
@ -51,6 +51,18 @@ ispkgin(const char **pkgs, int n)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
isforkfunc(Node *fn)
|
||||||
|
{
|
||||||
|
// Special case for syscall.forkAndExecInChild.
|
||||||
|
// In the child, this function must not acquire any locks, because
|
||||||
|
// they might have been locked at the time of the fork. This means
|
||||||
|
// no rescheduling, no malloc calls, and no new stack segments.
|
||||||
|
// Race instrumentation does all of the above.
|
||||||
|
return myimportpath != nil && strcmp(myimportpath, "syscall") == 0 &&
|
||||||
|
strcmp(fn->nname->sym->name, "forkAndExecInChild") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
racewalk(Node *fn)
|
racewalk(Node *fn)
|
||||||
{
|
{
|
||||||
|
|
@ -58,7 +70,7 @@ racewalk(Node *fn)
|
||||||
Node *nodpc;
|
Node *nodpc;
|
||||||
char s[1024];
|
char s[1024];
|
||||||
|
|
||||||
if(ispkgin(omit_pkgs, nelem(omit_pkgs)))
|
if(ispkgin(omit_pkgs, nelem(omit_pkgs)) || isforkfunc(fn))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!ispkgin(noinst_pkgs, nelem(noinst_pkgs))) {
|
if(!ispkgin(noinst_pkgs, nelem(noinst_pkgs))) {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ type SysProcAttr struct {
|
||||||
// In the child, this function must not acquire any locks, because
|
// In the child, this function must not acquire any locks, because
|
||||||
// they might have been locked at the time of the fork. This means
|
// they might have been locked at the time of the fork. This means
|
||||||
// no rescheduling, no malloc calls, and no new stack segments.
|
// no rescheduling, no malloc calls, and no new stack segments.
|
||||||
|
// For the same reason compiler does not race instrument it.
|
||||||
// The calls to RawSyscall are okay because they are assembly
|
// The calls to RawSyscall are okay because they are assembly
|
||||||
// functions that do not grow the stack.
|
// functions that do not grow the stack.
|
||||||
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
|
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ type SysProcAttr struct {
|
||||||
// In the child, this function must not acquire any locks, because
|
// In the child, this function must not acquire any locks, because
|
||||||
// they might have been locked at the time of the fork. This means
|
// they might have been locked at the time of the fork. This means
|
||||||
// no rescheduling, no malloc calls, and no new stack segments.
|
// no rescheduling, no malloc calls, and no new stack segments.
|
||||||
|
// For the same reason compiler does not race instrument it.
|
||||||
// The calls to RawSyscall are okay because they are assembly
|
// The calls to RawSyscall are okay because they are assembly
|
||||||
// functions that do not grow the stack.
|
// functions that do not grow the stack.
|
||||||
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
|
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue