Commit 94b974a2 authored by Evan Shaw's avatar Evan Shaw Committed by Rob Pike

os: add Process.Kill and Process.Signal

R=alex.brainman, r, rsc, krasin, iant, rsc, r
CC=golang-dev
https://golang.org/cl/4437091
parent 7dd47326
......@@ -27,6 +27,7 @@ GOFILES_freebsd=\
sys_bsd.go\
exec_posix.go\
exec_unix.go\
signal_unix.go\
GOFILES_darwin=\
dir_unix.go\
......@@ -38,6 +39,7 @@ GOFILES_darwin=\
sys_bsd.go\
exec_posix.go\
exec_unix.go\
signal_unix.go\
GOFILES_linux=\
dir_unix.go\
......@@ -49,6 +51,7 @@ GOFILES_linux=\
sys_linux.go\
exec_posix.go\
exec_unix.go\
signal_unix.go\
GOFILES_windows=\
dir_windows.go\
......@@ -60,6 +63,7 @@ GOFILES_windows=\
sys_windows.go\
exec_posix.go\
exec_windows.go\
signal_windows.go\
GOFILES_plan9=\
dir_plan9.go\
......@@ -72,4 +76,12 @@ GOFILES_plan9=\
GOFILES+=$(GOFILES_$(GOOS))
CLEANFILES+=signal_unix.go signal_windows.go
include ../../Make.pkg
signal_unix.go: ../syscall/zerrors_$(GOOS)_$(GOARCH).go
./mkunixsignals.sh $< > $@ || rm -f $@
signal_windows.go: ../syscall/ztypes_$(GOOS)_$(GOARCH).go
./mkunixsignals.sh $< > $@ || rm -f $@
......@@ -4,7 +4,25 @@
package os
import "syscall"
import (
"runtime"
"syscall"
)
// A Signal can represent any operating system signal.
type Signal interface {
String() string
}
type UnixSignal int32
func (sig UnixSignal) String() string {
s := runtime.Signame(int32(sig))
if len(s) > 0 {
return s
}
return "UnixSignal"
}
// StartProcess starts a new process with the program, arguments and attributes
// specified by name, argv and attr.
......@@ -34,6 +52,11 @@ func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err E
return newProcess(pid, h), nil
}
// Kill causes the Process to exit immediately.
func (p *Process) Kill() Error {
return p.Signal(SIGKILL)
}
// Exec replaces the current process with an execution of the
// named binary, with arguments argv and environment envv.
// If successful, Exec never returns. If it fails, it returns an Error.
......
......@@ -45,6 +45,14 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
return w, nil
}
// Signal sends a signal to the Process.
func (p *Process) Signal(sig Signal) Error {
if e := syscall.Kill(p.Pid, int(sig.(UnixSignal))); e != 0 {
return Errno(e)
}
return nil
}
// Release releases any resources associated with the Process.
func (p *Process) Release() Error {
// NOOP for unix.
......
......@@ -20,13 +20,23 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
return nil, ErrorString("os: unexpected result from WaitForSingleObject")
}
var ec uint32
e = syscall.GetExitCodeProcess(uint32(p.handle), &ec)
e = syscall.GetExitCodeProcess(int32(p.handle), &ec)
if e != 0 {
return nil, NewSyscallError("GetExitCodeProcess", e)
}
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 {
switch sig.(UnixSignal) {
case SIGKILL:
e := syscall.TerminateProcess(int32(p.handle), 1)
return NewSyscallError("TerminateProcess", e)
}
return Errno(syscall.EWINDOWS)
}
func (p *Process) Release() Error {
if p.handle == -1 {
return EINVAL
......
......@@ -8,7 +8,7 @@ echo '// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT'
echo
cat <<EOH
package signal
package os
import (
"syscall"
......
......@@ -7,11 +7,5 @@ include ../../../Make.inc
TARG=os/signal
GOFILES=\
signal.go\
unix.go\
CLEANFILES+=unix.go
include ../../../Make.pkg
unix.go: ../../syscall/zerrors_$(GOOS)_$(GOARCH).go
./mkunix.sh $< > $@ || rm -f $@
......@@ -6,35 +6,20 @@
package signal
import (
"os"
"runtime"
"strconv"
)
// A Signal can represent any operating system signal.
type Signal interface {
String() string
}
type UnixSignal int32
func (sig UnixSignal) String() string {
s := runtime.Signame(int32(sig))
if len(s) > 0 {
return s
}
return "Signal " + strconv.Itoa(int(sig))
}
// Incoming is the global signal channel.
// All signals received by the program will be delivered to this channel.
var Incoming <-chan Signal
var Incoming <-chan os.Signal
func process(ch chan<- Signal) {
func process(ch chan<- os.Signal) {
for {
var mask uint32 = runtime.Sigrecv()
for sig := uint(0); sig < 32; sig++ {
if mask&(1<<sig) != 0 {
ch <- UnixSignal(sig)
ch <- os.UnixSignal(sig)
}
}
}
......@@ -42,7 +27,7 @@ func process(ch chan<- Signal) {
func init() {
runtime.Siginit()
ch := make(chan Signal) // Done here so Incoming can have type <-chan Signal
ch := make(chan os.Signal) // Done here so Incoming can have type <-chan Signal
Incoming = ch
go process(ch)
}
......@@ -5,6 +5,7 @@
package signal
import (
"os"
"syscall"
"testing"
)
......@@ -13,7 +14,7 @@ func TestSignal(t *testing.T) {
// Send this process a SIGHUP.
syscall.Syscall(syscall.SYS_KILL, uintptr(syscall.Getpid()), syscall.SIGHUP, 0)
if sig := (<-Incoming).(UnixSignal); sig != SIGHUP {
t.Errorf("signal was %v, want %v", sig, SIGHUP)
if sig := (<-Incoming).(os.UnixSignal); sig != os.SIGHUP {
t.Errorf("signal was %v, want %v", sig, os.SIGHUP)
}
}
......@@ -141,8 +141,9 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno
//sys GetQueuedCompletionStatus(cphandle int32, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (errno int)
//sys CancelIo(s uint32) (errno int)
//sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (errno int) = CreateProcessW
//sys OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle uint32, errno int)
//sys GetExitCodeProcess(handle uint32, exitcode *uint32) (errno int)
//sys OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle int32, errno int)
//sys TerminateProcess(handle int32, exitcode uint32) (errno int)
//sys GetExitCodeProcess(handle int32, exitcode *uint32) (errno int)
//sys GetStartupInfo(startupInfo *StartupInfo) (errno int) = GetStartupInfoW
//sys GetCurrentProcess() (pseudoHandle int32, errno int)
//sys DuplicateHandle(hSourceProcessHandle int32, hSourceHandle int32, hTargetProcessHandle int32, lpTargetHandle *int32, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (errno int)
......@@ -697,10 +698,6 @@ func BindToDevice(fd int, device string) (errno int) { return
// TODO(brainman): fix all needed for os
const (
SIGTRAP = 5
)
func Getpid() (pid int) { return -1 }
func Getppid() (ppid int) { return -1 }
......
......@@ -46,6 +46,7 @@ var (
procCancelIo = getSysProcAddr(modkernel32, "CancelIo")
procCreateProcessW = getSysProcAddr(modkernel32, "CreateProcessW")
procOpenProcess = getSysProcAddr(modkernel32, "OpenProcess")
procTerminateProcess = getSysProcAddr(modkernel32, "TerminateProcess")
procGetExitCodeProcess = getSysProcAddr(modkernel32, "GetExitCodeProcess")
procGetStartupInfoW = getSysProcAddr(modkernel32, "GetStartupInfoW")
procGetCurrentProcess = getSysProcAddr(modkernel32, "GetCurrentProcess")
......@@ -542,7 +543,7 @@ func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityA
return
}
func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle uint32, errno int) {
func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle int32, errno int) {
var _p0 uint32
if inheritHandle {
_p0 = 1
......@@ -550,7 +551,7 @@ func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle uint32, errn
_p0 = 0
}
r0, _, e1 := Syscall(procOpenProcess, 3, uintptr(da), uintptr(_p0), uintptr(pid))
handle = uint32(r0)
handle = int32(r0)
if handle == 0 {
if e1 != 0 {
errno = int(e1)
......@@ -563,7 +564,21 @@ func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle uint32, errn
return
}
func GetExitCodeProcess(handle uint32, exitcode *uint32) (errno int) {
func TerminateProcess(handle int32, exitcode uint32) (errno int) {
r1, _, e1 := Syscall(procTerminateProcess, 2, uintptr(handle), uintptr(exitcode), 0)
if int(r1) == 0 {
if e1 != 0 {
errno = int(e1)
} else {
errno = EINVAL
}
} else {
errno = 0
}
return
}
func GetExitCodeProcess(handle int32, exitcode *uint32) (errno int) {
r1, _, e1 := Syscall(procGetExitCodeProcess, 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0)
if int(r1) == 0 {
if e1 != 0 {
......
......@@ -48,6 +48,23 @@ const (
O_CLOEXEC = 0x80000
)
const (
// More invented values for signals
SIGHUP = 0x1
SIGINT = 0x2
SIGQUIT = 0x3
SIGILL = 0x4
SIGTRAP = 0x5
SIGABRT = 0x6
SIGBUS = 0x7
SIGFPE = 0x8
SIGKILL = 0x9
SIGSEGV = 0xb
SIGPIPE = 0xd
SIGALRM = 0xe
SIGTERM = 0xf
)
const (
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment