Skip to content

Commit 2a8df44

Browse files
committed
os: mark pipes returned by os.Pipe() as inheritable by default
Now that we don't automatically pass all inheritable handles to new processes, we can make pipes returned by os.Pipe() inheritable, just like they are on Unix. This then allows them to be passed through the SysProcAttr.AdditionalInheritedHandles parameter simply. Updates #44011. Fixes #21085. Change-Id: I8eae329fbc74f9dc7962136fa9aae8fb66879751 Reviewed-on: https://go-review.googlesource.com/c/go/+/288299 Trust: Jason A. Donenfeld <[email protected]> Trust: Alex Brainman <[email protected]> Run-TryBot: Jason A. Donenfeld <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Alex Brainman <[email protected]>
1 parent 5ff7ec9 commit 2a8df44

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

src/os/exec/exec_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,16 @@ func TestHelperProcess(*testing.T) {
915915
case "sleep":
916916
time.Sleep(3 * time.Second)
917917
os.Exit(0)
918+
case "pipehandle":
919+
handle, _ := strconv.ParseUint(args[0], 16, 64)
920+
pipe := os.NewFile(uintptr(handle), "")
921+
_, err := fmt.Fprint(pipe, args[1])
922+
if err != nil {
923+
fmt.Fprintf(os.Stderr, "writing to pipe failed: %v\n", err)
924+
os.Exit(1)
925+
}
926+
pipe.Close()
927+
os.Exit(0)
918928
default:
919929
fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd)
920930
os.Exit(2)

src/os/exec/exec_windows_test.go

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build windows
6+
// +build windows
7+
8+
package exec_test
9+
10+
import (
11+
"io"
12+
"os"
13+
"strconv"
14+
"syscall"
15+
"testing"
16+
)
17+
18+
func TestPipePassing(t *testing.T) {
19+
r, w, err := os.Pipe()
20+
if err != nil {
21+
t.Error(err)
22+
}
23+
const marker = "arrakis, dune, desert planet"
24+
childProc := helperCommand(t, "pipehandle", strconv.FormatUint(uint64(w.Fd()), 16), marker)
25+
childProc.SysProcAttr = &syscall.SysProcAttr{AdditionalInheritedHandles: []syscall.Handle{syscall.Handle(w.Fd())}}
26+
err = childProc.Start()
27+
if err != nil {
28+
t.Error(err)
29+
}
30+
w.Close()
31+
response, err := io.ReadAll(r)
32+
if err != nil {
33+
t.Error(err)
34+
}
35+
r.Close()
36+
if string(response) != marker {
37+
t.Errorf("got %q; want %q", string(response), marker)
38+
}
39+
err = childProc.Wait()
40+
if err != nil {
41+
t.Error(err)
42+
}
43+
}

src/os/file_windows.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -279,10 +279,11 @@ func rename(oldname, newname string) error {
279279
}
280280

281281
// Pipe returns a connected pair of Files; reads from r return bytes written to w.
282-
// It returns the files and an error, if any.
282+
// It returns the files and an error, if any. The Windows handles underlying
283+
// the returned files are marked as inheritable by child processes.
283284
func Pipe() (r *File, w *File, err error) {
284285
var p [2]syscall.Handle
285-
e := syscall.CreatePipe(&p[0], &p[1], nil, 0)
286+
e := syscall.Pipe(p[:])
286287
if e != nil {
287288
return nil, nil, NewSyscallError("pipe", e)
288289
}

0 commit comments

Comments
 (0)