Commit 122a558f authored by Dave Cheney's avatar Dave Cheney

os: fix data race on Process.done

Fixes #3969.

R=dvyukov, r, alex.brainman, minux.ma
CC=golang-dev
https://golang.org/cl/6462081
parent 922056d4
......@@ -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 {
......
......@@ -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
}
}
......
......@@ -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)
......
......@@ -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 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment