1
0
mirror of https://github.com/golang/go synced 2024-11-19 11:34:49 -07:00

os: don't permit Process.Signal after a successful Wait

R=dsymonds, rsc
CC=golang-dev
https://golang.org/cl/4689043
This commit is contained in:
Brad Fitzpatrick 2011-07-11 15:47:42 -07:00
parent d1f4e0d14e
commit d53385fd0c
4 changed files with 20 additions and 2 deletions

View File

@ -13,10 +13,11 @@ import (
type Process struct { type Process struct {
Pid int Pid int
handle int handle int
done bool // process has been successfuly waited on
} }
func newProcess(pid, handle int) *Process { func newProcess(pid, handle int) *Process {
p := &Process{pid, handle} p := &Process{Pid: pid, handle: handle}
runtime.SetFinalizer(p, (*Process).Release) runtime.SetFinalizer(p, (*Process).Release)
return p return p
} }

View File

@ -38,6 +38,9 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
if e != 0 { if e != 0 {
return nil, NewSyscallError("wait", e) return nil, NewSyscallError("wait", e)
} }
if options&WSTOPPED == 0 {
p.done = true
}
w = new(Waitmsg) w = new(Waitmsg)
w.Pid = pid1 w.Pid = pid1
w.WaitStatus = status w.WaitStatus = status
@ -47,6 +50,9 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
// Signal sends a signal to the Process. // Signal sends a signal to the Process.
func (p *Process) Signal(sig Signal) Error { 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 { if e := syscall.Kill(p.Pid, int(sig.(UnixSignal))); e != 0 {
return Errno(e) return Errno(e)
} }

View File

@ -24,11 +24,15 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
if e != 0 { if e != 0 {
return nil, NewSyscallError("GetExitCodeProcess", e) return nil, NewSyscallError("GetExitCodeProcess", e)
} }
p.done = true
return &Waitmsg{p.Pid, syscall.WaitStatus{s, ec}, new(syscall.Rusage)}, nil return &Waitmsg{p.Pid, syscall.WaitStatus{s, ec}, new(syscall.Rusage)}, nil
} }
// Signal sends a signal to the Process. // Signal sends a signal to the Process.
func (p *Process) Signal(sig Signal) Error { func (p *Process) Signal(sig Signal) Error {
if p.done {
return NewError("os: process already finished")
}
switch sig.(UnixSignal) { switch sig.(UnixSignal) {
case SIGKILL: case SIGKILL:
e := syscall.TerminateProcess(syscall.Handle(p.handle), 1) e := syscall.TerminateProcess(syscall.Handle(p.handle), 1)

View File

@ -895,7 +895,14 @@ func run(t *testing.T, cmd []string) string {
var b bytes.Buffer var b bytes.Buffer
io.Copy(&b, r) 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() output := b.String()
if n := len(output); n > 0 && output[n-1] == '\n' { if n := len(output); n > 0 && output[n-1] == '\n' {
output = output[0 : n-1] output = output[0 : n-1]