]> Cypherpunks repositories - gostls13.git/commitdiff
os: implement new Process api
authorAlex Brainman <alex.brainman@gmail.com>
Fri, 4 Feb 2011 03:41:26 +0000 (14:41 +1100)
committerAlex Brainman <alex.brainman@gmail.com>
Fri, 4 Feb 2011 03:41:26 +0000 (14:41 +1100)
Fixes #1004.
Fixes #1460.

R=mattn, r, niemeyer, rog, rsc
CC=golang-dev
https://golang.org/cl/4029053

13 files changed:
src/cmd/cgo/util.go
src/cmd/godoc/main.go
src/pkg/exec/exec.go
src/pkg/http/triv.go
src/pkg/os/Makefile
src/pkg/os/exec.go
src/pkg/os/exec_unix.go [new file with mode: 0644]
src/pkg/os/exec_windows.go [new file with mode: 0644]
src/pkg/os/os_test.go
src/pkg/syscall/exec_unix.go
src/pkg/syscall/exec_windows.go
src/pkg/syscall/syscall_windows.go
src/pkg/syscall/zsyscall_windows_386.go

index a6f509dc48cfa02b5ceba3173c57a8678d54081b..59529a6d2430fa3b66d7abf18d0fd64252140968 100644 (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)
        }
index f1b11a760c593b373611b5b5dad1e2414839d733..968b8e0f95d42a4e1403ba1c9004f6f891ab5285 100644 (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()
index 4f4c8c777019e9c78e90982f3047bab65d038ed6..80f6f3c7dd489d28535e026501c2b4852c26ff35 100644 (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
                }
        }
index 03cfafa7b82edc622a182dbce4d2e0d6b67ca26a..52d521d3db3a3f444251d4cc9a627a504d9fa6c9 100644 (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
index f6caf084ccaa591dada88ab599d1fcebbf2123dd..3a81afe39a4f2cc39dd1b38141d22229b8190054 100644 (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))
 
index 100d984d170247633f8e75156023d3340b11a8de..dbdfacc5857744f5426ac550e63ece539e70efdf 100644 (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
-       }
-       pid1, e := syscall.Wait4(pid, &status, options, rusage)
-       if e != 0 {
-               return nil, NewSyscallError("wait", e)
+       p, e := FindProcess(pid)
+       if e != nil {
+               return nil, 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.
diff --git a/src/pkg/os/exec_unix.go b/src/pkg/os/exec_unix.go
new file mode 100644 (file)
index 0000000..8990d6a
--- /dev/null
@@ -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
+}
diff --git a/src/pkg/os/exec_windows.go b/src/pkg/os/exec_windows.go
new file mode 100644 (file)
index 0000000..73c0104
--- /dev/null
@@ -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
+}
index 49b58c83c80b899d856c128cee98a94162cf62c2..2ea8acdc43003a936bd9eb9b029d17f52b5d002b 100644 (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]
index c7f7893e7d81e9c2545aebfb987ce99567d90517..04c066918f8941569ddfeef6455024ce76ebff34 100644 (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
+}
index 64a0030dc6b5da4a7b08b113187692398ca9047b..1ce26550666e9147663169e5944a37d2d741e5bd 100644 (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
index 267b30647fbe882fc033937e2d4c7a75e5fd73bb..f0b71dd91d3aec527acaef40380452078d2a707e 100644 (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 }
index d5f170fe39abb29d98e93afe87e3f8c500f086b1..96c6098ddb243f8c8d4870c931cc05a277e9a425 100644 (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))