mirror of https://github.com/golang/go.git
exec: add Command.ExtraFiles
Allows passing extra fds to the child process. Fixes #2329 R=rsc, dsymonds CC=golang-dev https://golang.org/cl/5162050
This commit is contained in:
parent
029c9bcb8b
commit
155e21cc7f
|
|
@ -63,6 +63,11 @@ type Cmd struct {
|
||||||
Stdout io.Writer
|
Stdout io.Writer
|
||||||
Stderr io.Writer
|
Stderr io.Writer
|
||||||
|
|
||||||
|
// ExtraFiles specifies additional open files to be inherited by the
|
||||||
|
// new process. It does not include standard input, standard output, or
|
||||||
|
// standard error. If non-nil, entry i becomes file descriptor 3+i.
|
||||||
|
ExtraFiles []*os.File
|
||||||
|
|
||||||
// SysProcAttr holds optional, operating system-specific attributes.
|
// SysProcAttr holds optional, operating system-specific attributes.
|
||||||
// Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
|
// Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
|
||||||
SysProcAttr *syscall.SysProcAttr
|
SysProcAttr *syscall.SysProcAttr
|
||||||
|
|
@ -224,6 +229,7 @@ func (c *Cmd) Start() os.Error {
|
||||||
}
|
}
|
||||||
c.childFiles = append(c.childFiles, fd)
|
c.childFiles = append(c.childFiles, fd)
|
||||||
}
|
}
|
||||||
|
c.childFiles = append(c.childFiles, c.ExtraFiles...)
|
||||||
|
|
||||||
var err os.Error
|
var err os.Error
|
||||||
c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{
|
c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,10 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"testing"
|
"testing"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
@ -139,6 +141,39 @@ func TestPipes(t *testing.T) {
|
||||||
check("Wait", err)
|
check("Wait", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExtraFiles(t *testing.T) {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
t.Logf("no operating system support; skipping")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tf, err := ioutil.TempFile("", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("TempFile: %v", err)
|
||||||
|
}
|
||||||
|
defer os.Remove(tf.Name())
|
||||||
|
defer tf.Close()
|
||||||
|
|
||||||
|
const text = "Hello, fd 3!"
|
||||||
|
_, err = tf.Write([]byte(text))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Write: %v", err)
|
||||||
|
}
|
||||||
|
_, err = tf.Seek(0, os.SEEK_SET)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Seek: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := helperCommand("read3")
|
||||||
|
c.ExtraFiles = []*os.File{tf}
|
||||||
|
bs, err := c.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CombinedOutput: %v", err)
|
||||||
|
}
|
||||||
|
if string(bs) != text {
|
||||||
|
t.Errorf("got %q; want %q", string(bs), text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestHelperProcess isn't a real test. It's used as a helper process
|
// TestHelperProcess isn't a real test. It's used as a helper process
|
||||||
// for TestParameterRun.
|
// for TestParameterRun.
|
||||||
func TestHelperProcess(*testing.T) {
|
func TestHelperProcess(*testing.T) {
|
||||||
|
|
@ -204,6 +239,14 @@ func TestHelperProcess(*testing.T) {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "read3": // read fd 3
|
||||||
|
fd3 := os.NewFile(3, "fd3")
|
||||||
|
bs, err := ioutil.ReadAll(fd3)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("ReadAll from fd 3: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
os.Stderr.Write(bs)
|
||||||
case "exit":
|
case "exit":
|
||||||
n, _ := strconv.Atoi(args[0])
|
n, _ := strconv.Atoi(args[0])
|
||||||
os.Exit(n)
|
os.Exit(n)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue