]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1] os: fix data race on Process.done
authorDave Cheney <dave@cheney.net>
Fri, 21 Sep 2012 19:54:41 +0000 (05:54 +1000)
committerDave Cheney <dave@cheney.net>
Fri, 21 Sep 2012 19:54:41 +0000 (05:54 +1000)
««« backport 4fc1c61c3c2c
os: fix data race on Process.done

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 531b87ca55671a179e20a43f04af36899316fbda..6681acfd43bf911ab06217d147d2f668affb7a72 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 41cc8c26f4ce7efd505887e606570f91b235c300..01f06e2cf93190089433a39be886ee71434add36 100644 (file)
@@ -38,7 +38,7 @@ func (note Plan9Note) String() string {
 }
 
 func (p *Process) signal(sig Signal) error {
-       if p.done {
+       if p.done() {
                return errors.New("os: process already finished")
        }
 
@@ -76,7 +76,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 {