diff options
Diffstat (limited to 'src/pkg/os/exec.go')
| -rw-r--r-- | src/pkg/os/exec.go | 61 | 
1 files changed, 27 insertions, 34 deletions
| diff --git a/src/pkg/os/exec.go b/src/pkg/os/exec.go index 100d984d1..dbdfacc58 100644 --- a/src/pkg/os/exec.go +++ b/src/pkg/os/exec.go @@ -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. | 
