]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: do not race instrument syscall.forkAndExecInChild
authorDmitriy Vyukov <dvyukov@google.com>
Tue, 16 Jul 2013 11:35:03 +0000 (15:35 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Tue, 16 Jul 2013 11:35:03 +0000 (15:35 +0400)
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

src/cmd/gc/racewalk.c
src/pkg/syscall/exec_bsd.go
src/pkg/syscall/exec_linux.go

index 4a905499097677be6aeda681df8e77da6fbaaecb..b214645fa5f3d9c3a09ae7039521d8ef222a36a2 100644 (file)
@@ -51,6 +51,18 @@ ispkgin(const char **pkgs, int n)
        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
 racewalk(Node *fn)
 {
@@ -58,7 +70,7 @@ racewalk(Node *fn)
        Node *nodpc;
        char s[1024];
 
-       if(ispkgin(omit_pkgs, nelem(omit_pkgs)))
+       if(ispkgin(omit_pkgs, nelem(omit_pkgs)) || isforkfunc(fn))
                return;
 
        if(!ispkgin(noinst_pkgs, nelem(noinst_pkgs))) {
index 5d3d57813e50bc3f32e75dc5bd1576ccf7ced77c..249fa638ddabb1eeaf7732a5e3a6012b645f1175 100644 (file)
@@ -27,6 +27,7 @@ type SysProcAttr struct {
 // 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.
+// For the same reason compiler does not race instrument it.
 // The calls to RawSyscall are okay because they are assembly
 // 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) {
index ddd946ed20e81ae993383e6f1aea0bb76b5e17b5..934c65771200e03cd499f2b366443ff81534dbde 100644 (file)
@@ -28,6 +28,7 @@ type SysProcAttr struct {
 // 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.
+// For the same reason compiler does not race instrument it.
 // The calls to RawSyscall are okay because they are assembly
 // 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) {