Closed
Description
go1.7, go1.8rc3
When using a Context
to cancel an exec.Cmd
, if either of the outputs are an io.Writer
which isn't an *os.File
the command will fail to terminate.
The following panics on amd64 linux
ctx, cancel := context.WithCancel(context.Background())
cmd := exec.CommandContext(ctx, "/bin/sh", "-c", "sleep 60")
var output bytes.Buffer
cmd.Stdout = &output
cmd.Start()
log.Println("started command")
done := make(chan error)
go func() {
done <- cmd.Wait()
}()
time.Sleep(50 * time.Millisecond)
log.Println("canceling command")
cancel()
select {
case err := <-done:
log.Println("done:", err)
case <-time.After(time.Second):
panic("failed to cancel")
The full stack trace is:
main.main()
/home/user/command_context.go:35 +0x499
goroutine 5 [syscall]:
syscall.Syscall(0x0, 0x4, 0xc420092000, 0x200, 0x7f15a35f4000, 0x19, 0xc420092000)
/usr/local/go/src/syscall/asm_linux_amd64.s:18 +0x5
syscall.read(0x4, 0xc420092000, 0x200, 0x200, 0xc420026400, 0x7f15a35f4000, 0x0)
/usr/local/go/src/syscall/zsyscall_linux_amd64.go:783 +0x55
syscall.Read(0x4, 0xc420092000, 0x200, 0x200, 0x425b5f, 0x4dd550, 0xc420023dc0)
/usr/local/go/src/syscall/syscall_unix.go:162 +0x49
os.(*File).read(0xc42000c038, 0xc420092000, 0x200, 0x200, 0x4602ab, 0x4b38e0, 0x200)
/usr/local/go/src/os/file_unix.go:165 +0x4f
os.(*File).Read(0xc42000c038, 0xc420092000, 0x200, 0x200, 0x0, 0x7f15a3598028, 0xc420023e60)
/usr/local/go/src/os/file.go:101 +0x76
bytes.(*Buffer).ReadFrom(0xc420048070, 0x5381e0, 0xc42000c038, 0x7f15a3598028, 0xc420048070, 0x1)
/usr/local/go/src/bytes/buffer.go:179 +0x160
io.copyBuffer(0x538120, 0xc420048070, 0x5381e0, 0xc42000c038, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/usr/local/go/src/io/io.go:384 +0x2cb
io.Copy(0x538120, 0xc420048070, 0x5381e0, 0xc42000c038, 0x0, 0x0, 0x0)
/usr/local/go/src/io/io.go:360 +0x68
os/exec.(*Cmd).writerDescriptor.func1(0x0, 0x0)
/usr/local/go/src/os/exec/exec.go:254 +0x4d
os/exec.(*Cmd).Start.func1(0xc42007e000, 0xc42000a2a0)
/usr/local/go/src/os/exec/exec.go:371 +0x27
created by os/exec.(*Cmd).Start
/usr/local/go/src/os/exec/exec.go:372 +0x4e4
goroutine 7 [chan receive]:
os/exec.(*Cmd).Wait(0xc42007e000, 0x0, 0x0)
/usr/local/go/src/os/exec/exec.go:443 +0x118
main.main.func1(0xc4200681e0, 0xc42007e000)
/home/user/command_context.go:24 +0x2b
created by main.main
/home/user/command_context.go:25 +0x1eb
exit status 2