]> Cypherpunks repositories - gostls13.git/commitdiff
os: don't permit Process.Signal after a successful Wait
authorBrad Fitzpatrick <bradfitz@golang.org>
Mon, 11 Jul 2011 22:47:42 +0000 (15:47 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Mon, 11 Jul 2011 22:47:42 +0000 (15:47 -0700)
R=dsymonds, rsc
CC=golang-dev
https://golang.org/cl/4689043

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

index e2234f14a065cf43f319a191b1ec4e221e712ba9..40e6c1774ee817228dabc9f2ab889f276be945b4 100644 (file)
@@ -13,10 +13,11 @@ import (
 type Process struct {
        Pid    int
        handle int
+       done   bool // process has been successfuly waited on
 }
 
 func newProcess(pid, handle int) *Process {
-       p := &Process{pid, handle}
+       p := &Process{Pid: pid, handle: handle}
        runtime.SetFinalizer(p, (*Process).Release)
        return p
 }
index cf5ea9b617eb15a9d665ed750662edc6ae70b701..8a4b2e1b8060913a30b00abd7633ff0d5d92d453 100644 (file)
@@ -38,6 +38,9 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
        if e != 0 {
                return nil, NewSyscallError("wait", e)
        }
+       if options&WSTOPPED == 0 {
+               p.done = true
+       }
        w = new(Waitmsg)
        w.Pid = pid1
        w.WaitStatus = status
@@ -47,6 +50,9 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
 
 // Signal sends a signal to the Process.
 func (p *Process) Signal(sig Signal) Error {
+       if p.done {
+               return NewError("os: process already finished")
+       }
        if e := syscall.Kill(p.Pid, int(sig.(UnixSignal))); e != 0 {
                return Errno(e)
        }
index 5b432d39884e6a8444ac23c39631a6eab15cb114..65e94ac4acc8c4dfcd7da6ca07aec9543ddc570f 100644 (file)
@@ -24,11 +24,15 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
        if e != 0 {
                return nil, NewSyscallError("GetExitCodeProcess", e)
        }
+       p.done = true
        return &Waitmsg{p.Pid, syscall.WaitStatus{s, ec}, new(syscall.Rusage)}, nil
 }
 
 // Signal sends a signal to the Process.
 func (p *Process) Signal(sig Signal) Error {
+       if p.done {
+               return NewError("os: process already finished")
+       }
        switch sig.(UnixSignal) {
        case SIGKILL:
                e := syscall.TerminateProcess(syscall.Handle(p.handle), 1)
index c22b536d55734aae7bb88ab6bec31110d3c7a34b..dadae03e8cfb16f0bf661aaa0a7f67fbeec6af23 100644 (file)
@@ -895,7 +895,14 @@ func run(t *testing.T, cmd []string) string {
 
        var b bytes.Buffer
        io.Copy(&b, r)
-       p.Wait(0)
+       _, err = p.Wait(0)
+       if err != nil {
+               t.Fatalf("run hostname Wait: %v", err)
+       }
+       err = p.Kill()
+       if err == nil {
+               t.Errorf("expected an error from Kill running 'hostname'")
+       }
        output := b.String()
        if n := len(output); n > 0 && output[n-1] == '\n' {
                output = output[0 : n-1]