diff options
| author | Russ Cox <rsc@golang.org> | 2009-02-15 19:35:52 -0800 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2009-02-15 19:35:52 -0800 |
| commit | 91ceda5c18fdf7c7512b0a36725d9d5cf1c2b23f (patch) | |
| tree | 9600ec63eb31a171bc1f911505eae0806b9d33d5 /src/lib/os | |
| parent | 97dcc68f1ec4202b467210dcd2607c7630bb9d6e (diff) | |
| download | go-91ceda5c18fdf7c7512b0a36725d9d5cf1c2b23f.tar.xz | |
add os.ForkExec, os.Exec, os.Wait, exec.OpenCmd.
as thread-safe as possible, given the surrounding system.
add stub RWLock implementation.
R=r
DELTA=852 (834 added, 6 deleted, 12 changed)
OCL=25046
CL=25053
Diffstat (limited to 'src/lib/os')
| -rw-r--r-- | src/lib/os/Makefile | 7 | ||||
| -rw-r--r-- | src/lib/os/exec.go | 70 | ||||
| -rw-r--r-- | src/lib/os/file.go | 26 |
3 files changed, 97 insertions, 6 deletions
diff --git a/src/lib/os/Makefile b/src/lib/os/Makefile index ac0d3394d8..413a8d1b1b 100644 --- a/src/lib/os/Makefile +++ b/src/lib/os/Makefile @@ -3,8 +3,8 @@ # license that can be found in the LICENSE file. # DO NOT EDIT. Automatically generated by gobuild. -# gobuild -m dir_amd64_linux.go env.go error.go file.go stat_amd64_linux.go\ -# time.go types.go >Makefile +# gobuild -m dir_${GOARCH}_${GOOS}.go env.go error.go file.go\ +# stat_${GOARCH}_${GOOS}.go time.go types.go exec.go >Makefile O=6 GC=$(O)g CC=$(O)c -w @@ -46,6 +46,7 @@ O3=\ O4=\ dir_$(GOARCH)_$(GOOS).$O\ + exec.$O\ os.a: a1 a2 a3 a4 @@ -62,7 +63,7 @@ a3: $(O3) rm -f $(O3) a4: $(O4) - $(AR) grc os.a dir_$(GOARCH)_$(GOOS).$O + $(AR) grc os.a dir_$(GOARCH)_$(GOOS).$O exec.$O rm -f $(O4) newpkg: clean diff --git a/src/lib/os/exec.go b/src/lib/os/exec.go new file mode 100644 index 0000000000..0ce51773c5 --- /dev/null +++ b/src/lib/os/exec.go @@ -0,0 +1,70 @@ +// 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 ( + "os"; + "syscall"; +) + +func ForkExec(argv0 string, argv []string, envv []string, fd []*FD) + (pid int, err *Error) +{ + // Create array of integer (system) fds. + intfd := make([]int64, len(fd)); + for i, f := range(fd) { + if f == nil { + intfd[i] = -1; + } else { + intfd[i] = f.Fd(); + } + } + + p, e := syscall.ForkExec(argv0, argv, envv, intfd); + return int(p), ErrnoToError(e); +} + +func Exec(argv0 string, argv []string, envv []string) *Error { + e := syscall.Exec(argv0, argv, envv); + return ErrnoToError(e); +} + +// TODO(rsc): Should os implement its own syscall.WaitStatus +// wrapper with the methods, or is exposing the underlying one enough? +// +// TODO(rsc): Certainly need to have os.Rusage struct, +// since syscall one might have different field types across +// different OS. + +type Waitmsg struct { + Pid int; + syscall.WaitStatus; + Rusage *syscall.Rusage; +} + +const ( + WNOHANG = syscall.WNOHANG; + WSTOPPED = syscall.WSTOPPED; + WRUSAGE = 1<<60; +) + +func Wait(pid int, options uint64) (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(int64(pid), &status, int64(options), rusage); + if e != 0 { + return nil, ErrnoToError(e); + } + w = new(Waitmsg); + w.Pid = pid; + w.WaitStatus = status; + w.Rusage = rusage; + return w, nil; +} + diff --git a/src/lib/os/file.go b/src/lib/os/file.go index d4725760de..24aab1256d 100644 --- a/src/lib/os/file.go +++ b/src/lib/os/file.go @@ -4,8 +4,10 @@ package os -import syscall "syscall" -import os "os" +import ( + "os"; + "syscall"; +) // Auxiliary information if the FD describes a directory type dirInfo struct { // TODO(r): 6g bug means this can't be private @@ -57,7 +59,17 @@ const ( ) func Open(name string, mode int, flags int) (fd *FD, err *Error) { - r, e := syscall.Open(name, int64(mode), int64(flags)); + r, e := syscall.Open(name, int64(mode), int64(flags | syscall.O_CLOEXEC)); + if e != 0 { + return nil, ErrnoToError(e); + } + + // There's a race here with fork/exec, which we are + // content to live with. See ../syscall/exec.go + if syscall.O_CLOEXEC == 0 { // O_CLOEXEC not supported + syscall.CloseOnExec(r); + } + return NewFD(r, name), ErrnoToError(e) } @@ -122,10 +134,18 @@ func (fd *FD) WriteString(s string) (ret int, err *Error) { func Pipe() (fd1 *FD, fd2 *FD, err *Error) { var p [2]int64; + + // See ../syscall/exec.go for description of lock. + syscall.ForkLock.RLock(); r, e := syscall.Pipe(&p); if e != 0 { + syscall.ForkLock.RUnlock(); return nil, nil, ErrnoToError(e) } + syscall.CloseOnExec(p[0]); + syscall.CloseOnExec(p[1]); + syscall.ForkLock.RUnlock(); + return NewFD(p[0], "|0"), NewFD(p[1], "|1"), nil } |
