mirror of
https://github.com/golang/go
synced 2024-11-25 07:07:57 -07:00
syscall: implement WaitStatus and Wait4() for windows
R=brainman, rsc, kardia, Joe Poirier CC=golang-dev https://golang.org/cl/1910041
This commit is contained in:
parent
ded12ee4b5
commit
d3a2118b8a
@ -117,7 +117,6 @@ func SetNonblock(fd int, nonblocking bool) (errno int) {
|
||||
|
||||
// TODO(kardia): Add trace
|
||||
//The command and arguments are passed via the Command line parameter.
|
||||
//Thus, repeating the exec name in the first argument is unneeded.
|
||||
func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir string, fd []int) (pid int, err int) {
|
||||
if traceme == true {
|
||||
return 0, EWINDOWS
|
||||
@ -150,23 +149,28 @@ func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri
|
||||
if ok, err := DuplicateHandle(currentProc, int32(fd[0]), currentProc, &startupInfo.StdInput, 0, true, DUPLICATE_SAME_ACCESS); !ok {
|
||||
return 0, err
|
||||
}
|
||||
defer CloseHandle(int32(startupInfo.StdInput))
|
||||
}
|
||||
if len(fd) > 1 && fd[1] > 0 {
|
||||
if ok, err := DuplicateHandle(currentProc, int32(fd[1]), currentProc, &startupInfo.StdOutput, 0, true, DUPLICATE_SAME_ACCESS); !ok {
|
||||
return 0, err
|
||||
}
|
||||
defer CloseHandle(int32(startupInfo.StdOutput))
|
||||
}
|
||||
if len(fd) > 2 && fd[2] > 0 {
|
||||
if ok, err := DuplicateHandle(currentProc, int32(fd[2]), currentProc, &startupInfo.StdErr, 0, true, DUPLICATE_SAME_ACCESS); !ok {
|
||||
return 0, err
|
||||
}
|
||||
defer CloseHandle(int32(startupInfo.StdErr))
|
||||
}
|
||||
if len(argv) == 0 {
|
||||
argv = []string{""}
|
||||
}
|
||||
|
||||
// argv0 must not be longer then 256 chars
|
||||
// but the entire cmd line can have up to 32k chars (msdn)
|
||||
ok, err := CreateProcess(
|
||||
nil,
|
||||
StringToUTF16Ptr(escapeAddQuotes(argv0)+" "+stringJoin(argv, " ", escapeAddQuotes)),
|
||||
StringToUTF16Ptr(escapeAddQuotes(argv0)+" "+stringJoin(argv[1:], " ", escapeAddQuotes)),
|
||||
nil, //ptr to struct lpProcessAttributes
|
||||
nil, //ptr to struct lpThreadAttributes
|
||||
true, //bInheritHandles
|
||||
|
@ -137,6 +137,8 @@ func getSysProcAddr(m uint32, pname string) uintptr {
|
||||
//sys CryptAcquireContext(provhandle *uint32, container *uint16, provider *uint16, provtype uint32, flags uint32) (ok bool, errno int) = advapi32.CryptAcquireContextW
|
||||
//sys CryptReleaseContext(provhandle uint32, flags uint32) (ok bool, errno int) = advapi32.CryptReleaseContext
|
||||
//sys CryptGenRandom(provhandle uint32, buflen uint32, buf *byte) (ok bool, errno int) = advapi32.CryptGenRandom
|
||||
//sys OpenProcess(da uint32,b int, pid uint32) (handle uint32, errno int)
|
||||
//sys GetExitCodeProcess(h uint32, c *uint32) (ok bool, errno int)
|
||||
//sys GetEnvironmentStrings() (envs *uint16, errno int) [failretval=nil] = kernel32.GetEnvironmentStringsW
|
||||
//sys FreeEnvironmentStrings(envs *uint16) (ok bool, errno int) = kernel32.FreeEnvironmentStringsW
|
||||
//sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, errno int) = kernel32.GetEnvironmentVariableW
|
||||
@ -691,15 +693,35 @@ type Rusage struct {
|
||||
Nivcsw int32
|
||||
}
|
||||
|
||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
|
||||
return 0, EWINDOWS
|
||||
type WaitStatus struct {
|
||||
Status uint32
|
||||
ExitCode uint32
|
||||
}
|
||||
|
||||
type WaitStatus uint32
|
||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
|
||||
handle, errno := OpenProcess(PROCESS_ALL_ACCESS, 0, uint32(pid))
|
||||
if errno != 0 {
|
||||
return 0, errno
|
||||
}
|
||||
defer CloseHandle(int32(handle))
|
||||
e, errno := WaitForSingleObject(int32(handle), INFINITE)
|
||||
var c uint32
|
||||
if ok, errno := GetExitCodeProcess(handle, &c); !ok {
|
||||
return 0, errno
|
||||
}
|
||||
*wstatus = WaitStatus{e, c}
|
||||
return pid, 0
|
||||
}
|
||||
|
||||
func (WaitStatus) Exited() bool { return false }
|
||||
|
||||
func (WaitStatus) ExitStatus() int { return -1 }
|
||||
func (w WaitStatus) Exited() bool { return w.Status == WAIT_OBJECT_0 }
|
||||
|
||||
func (w WaitStatus) ExitStatus() int {
|
||||
if w.Status == WAIT_OBJECT_0 {
|
||||
return int(w.ExitCode)
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func (WaitStatus) Signal() int { return -1 }
|
||||
|
||||
@ -711,6 +733,6 @@ func (WaitStatus) Continued() bool { return false }
|
||||
|
||||
func (WaitStatus) StopSignal() int { return -1 }
|
||||
|
||||
func (WaitStatus) Signaled() bool { return false }
|
||||
func (w WaitStatus) Signaled() bool { return w.Status == WAIT_OBJECT_0 }
|
||||
|
||||
func (WaitStatus) TrapCause() int { return -1 }
|
||||
|
@ -53,6 +53,8 @@ var (
|
||||
procCryptAcquireContextW = getSysProcAddr(modadvapi32, "CryptAcquireContextW")
|
||||
procCryptReleaseContext = getSysProcAddr(modadvapi32, "CryptReleaseContext")
|
||||
procCryptGenRandom = getSysProcAddr(modadvapi32, "CryptGenRandom")
|
||||
procOpenProcess = getSysProcAddr(modkernel32, "OpenProcess")
|
||||
procGetExitCodeProcess = getSysProcAddr(modkernel32, "GetExitCodeProcess")
|
||||
procGetEnvironmentStringsW = getSysProcAddr(modkernel32, "GetEnvironmentStringsW")
|
||||
procFreeEnvironmentStringsW = getSysProcAddr(modkernel32, "FreeEnvironmentStringsW")
|
||||
procGetEnvironmentVariableW = getSysProcAddr(modkernel32, "GetEnvironmentVariableW")
|
||||
@ -679,6 +681,36 @@ func CryptGenRandom(provhandle uint32, buflen uint32, buf *byte) (ok bool, errno
|
||||
return
|
||||
}
|
||||
|
||||
func OpenProcess(da uint32, b int, pid uint32) (handle uint32, errno int) {
|
||||
r0, _, e1 := Syscall(procOpenProcess, uintptr(da), uintptr(b), uintptr(pid))
|
||||
handle = (uint32)(r0)
|
||||
if handle == 0 {
|
||||
if e1 != 0 {
|
||||
errno = int(e1)
|
||||
} else {
|
||||
errno = EINVAL
|
||||
}
|
||||
} else {
|
||||
errno = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetExitCodeProcess(h uint32, c *uint32) (ok bool, errno int) {
|
||||
r0, _, e1 := Syscall(procGetExitCodeProcess, uintptr(h), uintptr(unsafe.Pointer(c)), 0)
|
||||
ok = (bool)(r0 != 0)
|
||||
if !ok {
|
||||
if e1 != 0 {
|
||||
errno = int(e1)
|
||||
} else {
|
||||
errno = EINVAL
|
||||
}
|
||||
} else {
|
||||
errno = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetEnvironmentStrings() (envs *uint16, errno int) {
|
||||
r0, _, e1 := Syscall(procGetEnvironmentStringsW, 0, 0, 0)
|
||||
envs = (*uint16)(unsafe.Pointer(r0))
|
||||
|
@ -105,6 +105,9 @@ const (
|
||||
INFINITE = 0xffffffff
|
||||
|
||||
WAIT_TIMEOUT = 258
|
||||
WAIT_ABANDONED = 0x00000080
|
||||
WAIT_OBJECT_0 = 0x00000000
|
||||
WAIT_FAILED = 0xFFFFFFFF
|
||||
|
||||
CREATE_UNICODE_ENVIRONMENT = 0x00000400
|
||||
)
|
||||
@ -473,3 +476,10 @@ type DNSRecord struct {
|
||||
Reserved uint32
|
||||
Data [40]byte
|
||||
}
|
||||
|
||||
const (
|
||||
HANDLE_FLAG_INHERIT = 0x00000001
|
||||
HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002
|
||||
|
||||
PROCESS_ALL_ACCESS = 0x001fffff
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user