Closed
Description
go version go1.4 windows/amd64
Looks like there is a data race between os.Process.Wait() and os.Process.Kill(). The documentation does not state these operations can be run concurrently, but if they cannot, can you suggest a way to implement some kind of timeout on started process? Like "kill it if it runs more than N seconds".
The following code triggers the issue:
package main
import (
"fmt"
"os"
"os/exec"
"strconv"
"sync"
"time"
)
func spawnAndKill(exePath string, counter int) error {
cmd := exec.Command(exePath, fmt.Sprintf("%d", counter))
err := cmd.Start()
if err != nil {
return err
}
go func() {
time.Sleep(1000 * time.Millisecond)
cmd.Process.Kill()
}()
cmd.Wait()
return nil
}
func main() {
args := os.Args[1:]
if len(args) > 0 {
delay, err := strconv.ParseInt(args[0], 10, 32)
if err != nil {
panic("invalid input: " + args[0])
}
time.Sleep(time.Duration(delay) * time.Millisecond)
return
}
exePath := os.Args[0]
fmt.Printf("exe: %s\n", exePath)
jobs := &sync.WaitGroup{}
for j := 0; j < 100; j++ {
jobs.Add(1)
go func(id int) {
defer jobs.Done()
counter := 0
for {
err := spawnAndKill(exePath, counter%2000)
if err != nil {
fmt.Printf("spawn error: %s\n", err)
return
}
counter += 1
}
}(j)
}
jobs.Wait()
}
when run with:
go install -race race && GOMAXPROCS=100 GORACE="halt_on_error=1" bin/race.exe
and triggers:
exe: F:\dev\master\sword2\bin\race.exe
==================
WARNING: DATA RACE
Read by goroutine 106:
os.(*Process).signal()
c:/go/src/os/exec_windows.go:56 +0x5a
os.(*Process).Signal()
c:/go/src/os/doc.go:51 +0x62
os.(*Process).kill()
c:/go/src/os/exec_posix.go:53 +0x76
os.(*Process).Kill()
c:/go/src/os/doc.go:36 +0x4e
main.func·001()
F:/dev/master/sword2/src/race/race.go:20 +0x83
Previous write by goroutine 6:
os.(*Process).release()
c:/go/src/os/exec_windows.go:77 +0x2c2
os.(*Process).Release()
c:/go/src/os/doc.go:31 +0x4e
os.(*Process).wait()
c:/go/src/os/exec_windows.go:42 +0x64c
os.(*Process).Wait()
c:/go/src/os/doc.go:45 +0x4e
os/exec.(*Cmd).Wait()
c:/go/src/os/exec/exec.go:364 +0x315
main.spawnAndKill()
F:/dev/master/sword2/src/race/race.go:22 +0x360
main.func·002()
F:/dev/master/sword2/src/race/race.go:46 +0xe1
Goroutine 106 (running) created at:
main.spawnAndKill()
F:/dev/master/sword2/src/race/race.go:21 +0x340
main.func·002()
F:/dev/master/sword2/src/race/race.go:46 +0xe1
Goroutine 6 (running) created at:
main.main()
F:/dev/master/sword2/src/race/race.go:53 +0x539
==================