mirror of
https://github.com/golang/go
synced 2024-11-19 09:04:41 -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:
parent
d1f4e0d14e
commit
d53385fd0c
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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]
|
||||||
|
Loading…
Reference in New Issue
Block a user