1
0
mirror of https://github.com/golang/go synced 2024-11-22 00:24:41 -07:00

os: implement new Process api

Fixes #1004.
Fixes #1460.

R=mattn, r, niemeyer, rog, rsc
CC=golang-dev
https://golang.org/cl/4029053
This commit is contained in:
Alex Brainman 2011-02-04 14:41:26 +11:00
parent 8b9d6e38be
commit 4ecebfea53
13 changed files with 282 additions and 202 deletions

View File

@ -32,10 +32,11 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
if err != nil {
fatal("%s", err)
}
pid, err := os.ForkExec(cmd, argv, os.Environ(), "", []*os.File{r0, w1, w2})
p, err := os.StartProcess(cmd, argv, os.Environ(), "", []*os.File{r0, w1, w2})
if err != nil {
fatal("%s", err)
}
defer p.Release()
r0.Close()
w1.Close()
w2.Close()
@ -55,7 +56,7 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
<-c
<-c
w, err := os.Wait(pid, 0)
w, err := p.Wait(0)
if err != nil {
fatal("%s", err)
}

View File

@ -83,20 +83,21 @@ func exec(rw http.ResponseWriter, args []string) (status int) {
if *verbose {
log.Printf("executing %v", args)
}
pid, err := os.ForkExec(bin, args, os.Environ(), *goroot, fds)
p, err := os.StartProcess(bin, args, os.Environ(), *goroot, fds)
defer r.Close()
w.Close()
if err != nil {
log.Printf("os.ForkExec(%q): %v", bin, err)
log.Printf("os.StartProcess(%q): %v", bin, err)
return 2
}
defer p.Release()
var buf bytes.Buffer
io.Copy(&buf, r)
wait, err := os.Wait(pid, 0)
wait, err := p.Wait(0)
if err != nil {
os.Stderr.Write(buf.Bytes())
log.Printf("os.Wait(%d, 0): %v", pid, err)
log.Printf("os.Wait(%d, 0): %v", p.Pid, err)
return 2
}
status = wait.ExitStatus()

View File

@ -22,12 +22,12 @@ const (
// Stdin, Stdout, and Stderr are Files representing pipes
// connected to the running command's standard input, output, and error,
// or else nil, depending on the arguments to Run.
// Pid is the running command's operating system process ID.
// Process represents the underlying operating system process.
type Cmd struct {
Stdin *os.File
Stdout *os.File
Stderr *os.File
Pid int
Stdin *os.File
Stdout *os.File
Stderr *os.File
Process *os.Process
}
// PathError records the name of a binary that was not
@ -88,24 +88,24 @@ func modeToFiles(mode, fd int) (*os.File, *os.File, os.Error) {
// If a parameter is Pipe, then the corresponding field (Stdin, Stdout, Stderr)
// of the returned Cmd is the other end of the pipe.
// Otherwise the field in Cmd is nil.
func Run(name string, argv, envv []string, dir string, stdin, stdout, stderr int) (p *Cmd, err os.Error) {
p = new(Cmd)
func Run(name string, argv, envv []string, dir string, stdin, stdout, stderr int) (c *Cmd, err os.Error) {
c = new(Cmd)
var fd [3]*os.File
if fd[0], p.Stdin, err = modeToFiles(stdin, 0); err != nil {
if fd[0], c.Stdin, err = modeToFiles(stdin, 0); err != nil {
goto Error
}
if fd[1], p.Stdout, err = modeToFiles(stdout, 1); err != nil {
if fd[1], c.Stdout, err = modeToFiles(stdout, 1); err != nil {
goto Error
}
if stderr == MergeWithStdout {
fd[2] = fd[1]
} else if fd[2], p.Stderr, err = modeToFiles(stderr, 2); err != nil {
} else if fd[2], c.Stderr, err = modeToFiles(stderr, 2); err != nil {
goto Error
}
// Run command.
p.Pid, err = os.ForkExec(name, argv, envv, dir, fd[0:])
c.Process, err = os.StartProcess(name, argv, envv, dir, fd[0:])
if err != nil {
goto Error
}
@ -118,7 +118,7 @@ func Run(name string, argv, envv []string, dir string, stdin, stdout, stderr int
if fd[2] != os.Stderr && fd[2] != fd[1] {
fd[2].Close()
}
return p, nil
return c, nil
Error:
if fd[0] != os.Stdin && fd[0] != nil {
@ -130,63 +130,67 @@ Error:
if fd[2] != os.Stderr && fd[2] != nil && fd[2] != fd[1] {
fd[2].Close()
}
if p.Stdin != nil {
p.Stdin.Close()
if c.Stdin != nil {
c.Stdin.Close()
}
if p.Stdout != nil {
p.Stdout.Close()
if c.Stdout != nil {
c.Stdout.Close()
}
if p.Stderr != nil {
p.Stderr.Close()
if c.Stderr != nil {
c.Stderr.Close()
}
if c.Process != nil {
c.Process.Release()
}
return nil, err
}
// Wait waits for the running command p,
// returning the Waitmsg returned by os.Wait and an error.
// The options are passed through to os.Wait.
// Setting options to 0 waits for p to exit;
// Wait waits for the running command c,
// returning the Waitmsg returned when the process exits.
// The options are passed to the process's Wait method.
// Setting options to 0 waits for c to exit;
// other options cause Wait to return for other
// process events; see package os for details.
func (p *Cmd) Wait(options int) (*os.Waitmsg, os.Error) {
if p.Pid <= 0 {
func (c *Cmd) Wait(options int) (*os.Waitmsg, os.Error) {
if c.Process == nil {
return nil, os.ErrorString("exec: invalid use of Cmd.Wait")
}
w, err := os.Wait(p.Pid, options)
w, err := c.Process.Wait(options)
if w != nil && (w.Exited() || w.Signaled()) {
p.Pid = -1
c.Process.Release()
c.Process = nil
}
return w, err
}
// Close waits for the running command p to exit,
// Close waits for the running command c to exit,
// if it hasn't already, and then closes the non-nil file descriptors
// p.Stdin, p.Stdout, and p.Stderr.
func (p *Cmd) Close() os.Error {
if p.Pid > 0 {
// c.Stdin, c.Stdout, and c.Stderr.
func (c *Cmd) Close() os.Error {
if c.Process != nil {
// Loop on interrupt, but
// ignore other errors -- maybe
// caller has already waited for pid.
_, err := p.Wait(0)
_, err := c.Wait(0)
for err == os.EINTR {
_, err = p.Wait(0)
_, err = c.Wait(0)
}
}
// Close the FDs that are still open.
var err os.Error
if p.Stdin != nil && p.Stdin.Fd() >= 0 {
if err1 := p.Stdin.Close(); err1 != nil {
if c.Stdin != nil && c.Stdin.Fd() >= 0 {
if err1 := c.Stdin.Close(); err1 != nil {
err = err1
}
}
if p.Stdout != nil && p.Stdout.Fd() >= 0 {
if err1 := p.Stdout.Close(); err1 != nil && err != nil {
if c.Stdout != nil && c.Stdout.Fd() >= 0 {
if err1 := c.Stdout.Close(); err1 != nil && err != nil {
err = err1
}
}
if p.Stderr != nil && p.Stderr != p.Stdout && p.Stderr.Fd() >= 0 {
if err1 := p.Stderr.Close(); err1 != nil && err != nil {
if c.Stderr != nil && c.Stderr != c.Stdout && c.Stderr.Fd() >= 0 {
if err1 := c.Stderr.Close(); err1 != nil && err != nil {
err = err1
}
}

View File

@ -99,15 +99,16 @@ func DateServer(rw http.ResponseWriter, req *http.Request) {
fmt.Fprintf(rw, "pipe: %s\n", err)
return
}
pid, err := os.ForkExec("/bin/date", []string{"date"}, os.Environ(), "", []*os.File{nil, w, w})
p, err := os.StartProcess("/bin/date", []string{"date"}, os.Environ(), "", []*os.File{nil, w, w})
defer r.Close()
w.Close()
if err != nil {
fmt.Fprintf(rw, "fork/exec: %s\n", err)
return
}
defer p.Release()
io.Copy(rw, r)
wait, err := os.Wait(pid, 0)
wait, err := p.Wait(0)
if err != nil {
fmt.Fprintf(rw, "wait: %s\n", err)
return

View File

@ -22,21 +22,25 @@ GOFILES_freebsd=\
env_unix.go\
file_unix.go\
sys_bsd.go\
exec_unix.go\
GOFILES_darwin=\
env_unix.go\
file_unix.go\
sys_bsd.go\
exec_unix.go\
GOFILES_linux=\
env_unix.go\
file_unix.go\
sys_linux.go\
exec_unix.go\
GOFILES_windows=\
env_windows.go\
file_windows.go\
sys_windows.go\
exec_windows.go\
GOFILES+=$(GOFILES_$(GOOS))

View File

@ -5,17 +5,29 @@
package os
import (
"runtime"
"syscall"
)
// ForkExec forks the current process and invokes Exec with the program, arguments,
// and environment specified by name, argv, and envv. It returns the process
// id of the forked process and an Error, if any. The fd array specifies the
// Process stores the information about a process created by StartProcess.
type Process struct {
Pid int
handle int
}
func newProcess(pid, handle int) *Process {
p := &Process{pid, handle}
runtime.SetFinalizer(p, (*Process).Release)
return p
}
// StartProcess starts a new process with the program, arguments,
// and environment specified by name, argv, and envv. The fd array specifies the
// file descriptors to be set up in the new process: fd[0] will be Unix file
// descriptor 0 (standard input), fd[1] descriptor 1, and so on. A nil entry
// will cause the child to have no open file descriptor with that index.
// If dir is not empty, the child chdirs into the directory before execing the program.
func ForkExec(name string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) {
func StartProcess(name string, argv []string, envv []string, dir string, fd []*File) (p *Process, err Error) {
if envv == nil {
envv = Environ()
}
@ -29,17 +41,17 @@ func ForkExec(name string, argv []string, envv []string, dir string, fd []*File)
}
}
p, e := syscall.ForkExec(name, argv, envv, dir, intfd)
pid, h, e := syscall.StartProcess(name, argv, envv, dir, intfd)
if e != 0 {
return 0, &PathError{"fork/exec", name, Errno(e)}
return nil, &PathError{"fork/exec", name, Errno(e)}
}
return p, nil
return newProcess(pid, h), nil
}
// 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.
// ForkExec is almost always a better way to execute a program.
// StartProcess is almost always a better way to execute a program.
func Exec(name string, argv []string, envv []string) Error {
if envv == nil {
envv = Environ()
@ -65,37 +77,18 @@ type Waitmsg struct {
Rusage *syscall.Rusage // System-dependent resource usage info.
}
// Options for Wait.
const (
WNOHANG = syscall.WNOHANG // Don't wait if no process has exited.
WSTOPPED = syscall.WSTOPPED // If set, status of stopped subprocesses is also reported.
WUNTRACED = syscall.WUNTRACED // Usually an alias for WSTOPPED.
WRUSAGE = 1 << 20 // Record resource usage.
)
// WRUSAGE must not be too high a bit, to avoid clashing with Linux's
// WCLONE, WALL, and WNOTHREAD flags, which sit in the top few bits of
// the options
// Wait waits for process pid to exit or stop, and then returns a
// Waitmsg describing its status and an Error, if any. The options
// (WNOHANG etc.) affect the behavior of the Wait call.
// Wait is equivalent to calling FindProcess and then Wait
// and Release on the result.
func Wait(pid int, options int) (w *Waitmsg, err Error) {
var status syscall.WaitStatus
var rusage *syscall.Rusage
if options&WRUSAGE != 0 {
rusage = new(syscall.Rusage)
options ^= WRUSAGE
p, e := FindProcess(pid)
if e != nil {
return nil, e
}
pid1, e := syscall.Wait4(pid, &status, options, rusage)
if e != 0 {
return nil, NewSyscallError("wait", e)
}
w = new(Waitmsg)
w.Pid = pid1
w.WaitStatus = status
w.Rusage = rusage
return w, nil
defer p.Release()
return p.Wait(options)
}
// Convert i to decimal string.

63
src/pkg/os/exec_unix.go Normal file
View File

@ -0,0 +1,63 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package os
import (
"runtime"
"syscall"
)
// Options for Wait.
const (
WNOHANG = syscall.WNOHANG // Don't wait if no process has exited.
WSTOPPED = syscall.WSTOPPED // If set, status of stopped subprocesses is also reported.
WUNTRACED = syscall.WUNTRACED // Usually an alias for WSTOPPED.
WRUSAGE = 1 << 20 // Record resource usage.
)
// WRUSAGE must not be too high a bit, to avoid clashing with Linux's
// WCLONE, WALL, and WNOTHREAD flags, which sit in the top few bits of
// the options
// Wait waits for the Process to exit or stop, and then returns a
// Waitmsg describing its status and an Error, if any. The options
// (WNOHANG etc.) affect the behavior of the Wait call.
func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
if p.Pid == -1 {
return nil, EINVAL
}
var status syscall.WaitStatus
var rusage *syscall.Rusage
if options&WRUSAGE != 0 {
rusage = new(syscall.Rusage)
options ^= WRUSAGE
}
pid1, e := syscall.Wait4(p.Pid, &status, options, rusage)
if e != 0 {
return nil, NewSyscallError("wait", e)
}
w = new(Waitmsg)
w.Pid = pid1
w.WaitStatus = status
w.Rusage = rusage
return w, nil
}
// Release releases any resources associated with the Process.
func (p *Process) Release() Error {
// NOOP for unix.
p.Pid = -1
// no need for a finalizer anymore
runtime.SetFinalizer(p, nil)
return nil
}
// FindProcess looks for a running process by its pid.
// The Process it returns can be used to obtain information
// about the underlying operating system process.
func FindProcess(pid int) (p *Process, err Error) {
// NOOP for unix.
return newProcess(pid, 0), nil
}

View File

@ -0,0 +1,50 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package os
import (
"runtime"
"syscall"
)
func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
s, e := syscall.WaitForSingleObject(int32(p.handle), syscall.INFINITE)
switch s {
case syscall.WAIT_OBJECT_0:
break
case syscall.WAIT_FAILED:
return nil, NewSyscallError("WaitForSingleObject", e)
default:
return nil, ErrorString("os: unexpected result from WaitForSingleObject")
}
var ec uint32
if ok, e := syscall.GetExitCodeProcess(uint32(p.handle), &ec); !ok {
return nil, NewSyscallError("GetExitCodeProcess", e)
}
return &Waitmsg{p.Pid, syscall.WaitStatus{s, ec}, new(syscall.Rusage)}, nil
}
func (p *Process) Release() Error {
if p.handle == -1 {
return EINVAL
}
if ok, e := syscall.CloseHandle(int32(p.handle)); !ok {
return NewSyscallError("CloseHandle", e)
}
p.handle = -1
// no need for a finalizer anymore
runtime.SetFinalizer(p, nil)
return nil
}
func FindProcess(pid int) (p *Process, err Error) {
const da = syscall.STANDARD_RIGHTS_READ |
syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE
h, e := syscall.OpenProcess(da, false, uint32(pid))
if e != 0 {
return nil, NewSyscallError("OpenProcess", e)
}
return newProcess(pid, int(h)), nil
}

View File

@ -427,10 +427,11 @@ func TestForkExec(t *testing.T) {
adir = "/"
expect = "/\n"
}
pid, err := ForkExec(cmd, args, nil, adir, []*File{nil, w, Stderr})
p, err := StartProcess(cmd, args, nil, adir, []*File{nil, w, Stderr})
if err != nil {
t.Fatalf("ForkExec: %v", err)
t.Fatalf("StartProcess: %v", err)
}
defer p.Release()
w.Close()
var b bytes.Buffer
@ -440,7 +441,7 @@ func TestForkExec(t *testing.T) {
args[0] = cmd
t.Errorf("exec %q returned %q wanted %q", strings.Join(args, " "), output, expect)
}
Wait(pid, 0)
p.Wait(0)
}
func checkMode(t *testing.T, path string, mode uint32) {
@ -750,15 +751,16 @@ func run(t *testing.T, cmd []string) string {
if err != nil {
t.Fatal(err)
}
pid, err := ForkExec("/bin/hostname", []string{"hostname"}, nil, "/", []*File{nil, w, Stderr})
p, err := StartProcess("/bin/hostname", []string{"hostname"}, nil, "/", []*File{nil, w, Stderr})
if err != nil {
t.Fatal(err)
}
defer p.Release()
w.Close()
var b bytes.Buffer
io.Copy(&b, r)
Wait(pid, 0)
p.Wait(0)
output := b.String()
if n := len(output); n > 0 && output[n-1] == '\n' {
output = output[0 : n-1]

View File

@ -310,3 +310,9 @@ func Exec(argv0 string, argv []string, envv []string) (err int) {
uintptr(unsafe.Pointer(&StringArrayPtr(envv)[0])))
return int(err1)
}
// StartProcess wraps ForkExec for package os.
func StartProcess(argv0 string, argv []string, envv []string, dir string, fd []int) (pid, handle int, err int) {
pid, err = forkExec(argv0, argv, envv, false, dir, fd)
return pid, 0, err
}

View File

@ -117,13 +117,9 @@ func SetNonblock(fd int, nonblocking bool) (errno int) {
// TODO(kardia): Add trace
//The command and arguments are passed via the Command line parameter.
func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir string, fd []int) (pid int, err int) {
if traceme == true {
return 0, EWINDOWS
}
func StartProcess(argv0 string, argv []string, envv []string, dir string, fd []int) (pid, handle int, err int) {
if len(fd) > 3 {
return 0, EWINDOWS
return 0, 0, EWINDOWS
}
//CreateProcess will throw an error if the dir is not set to a valid dir
@ -153,19 +149,19 @@ func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri
var currentProc, _ = GetCurrentProcess()
if len(fd) > 0 && fd[0] > 0 {
if ok, err := DuplicateHandle(currentProc, int32(fd[0]), currentProc, &startupInfo.StdInput, 0, true, DUPLICATE_SAME_ACCESS); !ok {
return 0, err
return 0, 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
return 0, 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
return 0, 0, err
}
defer CloseHandle(int32(startupInfo.StdErr))
}
@ -188,21 +184,12 @@ func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri
if ok {
pid = int(processInfo.ProcessId)
CloseHandle(processInfo.Process)
handle = int(processInfo.Process)
CloseHandle(processInfo.Thread)
}
return
}
func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
return forkExec(argv0, argv, envv, false, dir, fd)
}
// PtraceForkExec is like ForkExec, but starts the child in a traced state.
func PtraceForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
return forkExec(argv0, argv, envv, true, dir, fd)
}
// Ordinary exec.
func Exec(argv0 string, argv []string, envv []string) (err int) {
return EWINDOWS

View File

@ -136,6 +136,8 @@ func NewCallback(fn interface{}) uintptr
//sys GetQueuedCompletionStatus(cphandle int32, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (ok bool, errno int)
//sys CancelIo(s uint32) (ok bool, errno int)
//sys CreateProcess(appName *int16, commandLine *uint16, procSecurity *int16, threadSecurity *int16, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (ok bool, errno int) = CreateProcessW
//sys OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle uint32, errno int)
//sys GetExitCodeProcess(handle uint32, exitcode *uint32) (ok bool, errno int)
//sys GetStartupInfo(startupInfo *StartupInfo) (ok bool, 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) (ok bool, errno int)
@ -146,8 +148,6 @@ func NewCallback(fn interface{}) 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
@ -672,6 +672,32 @@ func WSASendto(s uint32, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32
return
}
// Invented structures to support what package os expects.
type Rusage struct{}
type WaitStatus struct {
Status uint32
ExitCode uint32
}
func (w WaitStatus) Exited() bool { return true }
func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) }
func (w WaitStatus) Signal() int { return -1 }
func (w WaitStatus) CoreDump() bool { return false }
func (w WaitStatus) Stopped() bool { return false }
func (w WaitStatus) Continued() bool { return false }
func (w WaitStatus) StopSignal() int { return -1 }
func (w WaitStatus) Signaled() bool { return true }
func (w WaitStatus) TrapCause() int { return -1 }
// TODO(brainman): fix all needed for net
func Accept(fd int) (nfd int, sa Sockaddr, errno int) { return 0, nil, EWINDOWS }
@ -735,67 +761,3 @@ const (
SYS_EXIT
SYS_READ
)
type Rusage struct {
Utime Timeval
Stime Timeval
Maxrss int32
Ixrss int32
Idrss int32
Isrss int32
Minflt int32
Majflt int32
Nswap int32
Inblock int32
Oublock int32
Msgsnd int32
Msgrcv int32
Nsignals int32
Nvcsw int32
Nivcsw int32
}
type WaitStatus struct {
Status uint32
ExitCode uint32
}
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
const da = STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | SYNCHRONIZE
handle, errno := OpenProcess(da, 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 (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 }
func (WaitStatus) CoreDump() bool { return false }
func (WaitStatus) Stopped() bool { return false }
func (WaitStatus) Continued() bool { return false }
func (WaitStatus) StopSignal() int { return -1 }
func (w WaitStatus) Signaled() bool { return w.Status == WAIT_OBJECT_0 }
func (WaitStatus) TrapCause() int { return -1 }

View File

@ -45,6 +45,8 @@ var (
procGetQueuedCompletionStatus = getSysProcAddr(modkernel32, "GetQueuedCompletionStatus")
procCancelIo = getSysProcAddr(modkernel32, "CancelIo")
procCreateProcessW = getSysProcAddr(modkernel32, "CreateProcessW")
procOpenProcess = getSysProcAddr(modkernel32, "OpenProcess")
procGetExitCodeProcess = getSysProcAddr(modkernel32, "GetExitCodeProcess")
procGetStartupInfoW = getSysProcAddr(modkernel32, "GetStartupInfoW")
procGetCurrentProcess = getSysProcAddr(modkernel32, "GetCurrentProcess")
procDuplicateHandle = getSysProcAddr(modkernel32, "DuplicateHandle")
@ -55,8 +57,6 @@ 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")
@ -550,6 +550,42 @@ func CreateProcess(appName *int16, commandLine *uint16, procSecurity *int16, thr
return
}
func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle uint32, errno int) {
var _p0 uint32
if inheritHandle {
_p0 = 1
} else {
_p0 = 0
}
r0, _, e1 := Syscall(procOpenProcess, 3, uintptr(da), uintptr(_p0), uintptr(pid))
handle = uint32(r0)
if handle == 0 {
if e1 != 0 {
errno = int(e1)
} else {
errno = EINVAL
}
} else {
errno = 0
}
return
}
func GetExitCodeProcess(handle uint32, exitcode *uint32) (ok bool, errno int) {
r0, _, e1 := Syscall(procGetExitCodeProcess, 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0)
ok = bool(r0 != 0)
if !ok {
if e1 != 0 {
errno = int(e1)
} else {
errno = EINVAL
}
} else {
errno = 0
}
return
}
func GetStartupInfo(startupInfo *StartupInfo) (ok bool, errno int) {
r0, _, e1 := Syscall(procGetStartupInfoW, 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0)
ok = bool(r0 != 0)
@ -706,36 +742,6 @@ 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, 3, 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, 2, 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, 0)
envs = (*uint16)(unsafe.Pointer(r0))