]> Cypherpunks repositories - gostls13.git/commitdiff
os: fix data race on Process.done
authorDave Cheney <dave@cheney.net>
Tue, 21 Aug 2012 00:41:31 +0000 (10:41 +1000)
committerDave Cheney <dave@cheney.net>
Tue, 21 Aug 2012 00:41:31 +0000 (10:41 +1000)
Fixes #3969.

R=dvyukov, r, alex.brainman, minux.ma
CC=golang-dev
https://golang.org/cl/6462081

src/pkg/os/exec.go
src/pkg/os/exec_plan9.go
src/pkg/os/exec_unix.go
src/pkg/os/exec_windows.go

index eb6a4f825a1db3cf5b52e0d41e0e956f50a8ccbc..5aea3098b542354d27630d1cc51b66d6efd5c2fe 100644 (file)
@@ -6,6 +6,7 @@ package os
 
 import (
        "runtime"
+       "sync/atomic"
        "syscall"
 )
 
@@ -13,7 +14,7 @@ import (
 type Process struct {
        Pid    int
        handle uintptr
-       done   bool // process has been successfully waited on
+       isdone uint32 // process has been successfully waited on, non zero if true
 }
 
 func newProcess(pid int, handle uintptr) *Process {
@@ -22,6 +23,14 @@ func newProcess(pid int, handle uintptr) *Process {
        return p
 }
 
+func (p *Process) setDone() {
+       atomic.StoreUint32(&p.isdone, 1)
+}
+
+func (p *Process) done() bool {
+       return atomic.LoadUint32(&p.isdone) > 0
+}
+
 // ProcAttr holds the attributes that will be applied to a new process
 // started by StartProcess.
 type ProcAttr struct {
index ca2dfbf6bc3fb68dd2255dcfade07219fa86c018..2a7a597637354c451d8e61338150e5371272c6fe 100644 (file)
@@ -49,7 +49,7 @@ func (p *Process) writeProcFile(file string, data string) error {
 }
 
 func (p *Process) signal(sig Signal) error {
-       if p.done {
+       if p.done() {
                return errors.New("os: process already finished")
        }
        if sig == Kill {
@@ -84,7 +84,7 @@ func (p *Process) wait() (ps *ProcessState, err error) {
                }
 
                if waitmsg.Pid == p.Pid {
-                       p.done = true
+                       p.setDone()
                        break
                }
        }
index ecfe5353bc1f9ce84747ccb51f9b4ce944d39917..fa3ba8a19e4e13a081760e019eabb3a3ee48ee79 100644 (file)
@@ -24,7 +24,7 @@ func (p *Process) wait() (ps *ProcessState, err error) {
                return nil, NewSyscallError("wait", e)
        }
        if pid1 != 0 {
-               p.done = true
+               p.setDone()
        }
        ps = &ProcessState{
                pid:    pid1,
@@ -35,7 +35,7 @@ func (p *Process) wait() (ps *ProcessState, err error) {
 }
 
 func (p *Process) signal(sig Signal) error {
-       if p.done {
+       if p.done() {
                return errors.New("os: process already finished")
        }
        s, ok := sig.(syscall.Signal)
index 5beca4a6509650c80f14b3f49d64e1d05e368aad..4aa2ade631ed7b151ec831aaf3a083681f6923af 100644 (file)
@@ -32,7 +32,7 @@ func (p *Process) wait() (ps *ProcessState, err error) {
        if e != nil {
                return nil, NewSyscallError("GetProcessTimes", e)
        }
-       p.done = true
+       p.setDone()
        // NOTE(brainman): It seems that sometimes process is not dead
        // when WaitForSingleObject returns. But we do not know any
        // other way to wait for it. Sleeping for a while seems to do
@@ -43,7 +43,7 @@ func (p *Process) wait() (ps *ProcessState, err error) {
 }
 
 func (p *Process) signal(sig Signal) error {
-       if p.done {
+       if p.done() {
                return errors.New("os: process already finished")
        }
        if sig == Kill {