]> Cypherpunks repositories - gostls13.git/commitdiff
os: add Process.Kill and Process.Signal
authorEvan Shaw <chickencha@gmail.com>
Mon, 6 Jun 2011 09:53:30 +0000 (19:53 +1000)
committerRob Pike <r@golang.org>
Mon, 6 Jun 2011 09:53:30 +0000 (19:53 +1000)
R=alex.brainman, r, rsc, krasin, iant, rsc, r
CC=golang-dev
https://golang.org/cl/4437091

src/pkg/os/Makefile
src/pkg/os/exec_posix.go
src/pkg/os/exec_unix.go
src/pkg/os/exec_windows.go
src/pkg/os/mkunixsignals.sh [moved from src/pkg/os/signal/mkunix.sh with 96% similarity]
src/pkg/os/signal/Makefile
src/pkg/os/signal/signal.go
src/pkg/os/signal/signal_test.go
src/pkg/syscall/syscall_windows.go
src/pkg/syscall/zsyscall_windows_386.go
src/pkg/syscall/ztypes_windows_386.go

index c781df7af5ebe6f2d38ae37340e7143bde8167ac..497e5a95874255b92d8546ade6a676f5d92ceba8 100644 (file)
@@ -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 $@
index 9102dc0a4cb283e1bc8cd7b9bee721c8088d5a36..bf992ef42ef49774d8a368e2fff7e5b80f7689ce 100644 (file)
@@ -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.
index 8990d6a97ece5c8f7e8b1a5765a0fdb0f45b3266..cf5ea9b617eb15a9d665ed750662edc6ae70b701 100644 (file)
@@ -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.
index ae8ffeab2e9bd173ed98ecb73ad6276724ae3c78..bac33b908ba19b1ec6b7bad9a5afae9f559b2369 100644 (file)
@@ -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
similarity index 96%
rename from src/pkg/os/signal/mkunix.sh
rename to src/pkg/os/mkunixsignals.sh
index 653b016641607b2786c44fb90910ce9e6005cff3..6ec764cbd9b0dd10ce6c3bf6010c7d5a5e5dc90c 100755 (executable)
@@ -8,7 +8,7 @@ echo '// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT'
 echo
 
 cat <<EOH
-package signal
+package os
 
 import (
   "syscall"
index 013b91a8530cc8c8a93de8f2613964724cc54b31..26f58760e2b518370e495dba196823ddb62c7345 100644 (file)
@@ -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 $@
index 666c03e73c4ff87b5900353ffd315cbda8d597af..520f3f8a9ea49c4a1543dd1cac7d05568eb1e7e2 100644 (file)
@@ -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)
 }
index f2679f14dc6a13b3bc92504dbc3cb272566ac9ab..00eb29578f970bc212534f2117d87b4333154faa 100644 (file)
@@ -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)
        }
 }
index bb93533bd097f942091dcc04834c0f735539b9ac..d01664d126c032957b6081049ad068a18cf008f4 100644 (file)
@@ -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 }
 
index ce36ab6c0fa9741aac92855ea92aae86c658165a..447b09043e91baccf22bab4cf5e81743e27e10bf 100644 (file)
@@ -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 {
index 7b15ea4049cc4151768a15eb812d1d35faa23b05..b04fea5766cc00155099d550740857961777a64e 100644 (file)
@@ -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