go: os: Pipe can't be inherited on windows
What version of Go are you using (go version)?
go version go1.8.3 windows/amd64
What operating system and processor architecture are you using (go env)?
set GOARCH=amd64
set GOBIN=
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=C:\Users\light\go
set GORACE=
set GOROOT=C:\Go
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
set CXX=g++
set CGO_ENABLED=1
set PKG_CONFIG=pkg-config
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
What did you do?
https://play.golang.org/p/r5V40AgLht
What did you expect to see?
Parent process
Child process
Hello, World!
I would like to be able to pass an unnamed piped into a subprocess. According to MSDN docs, this seems like something that Windows is capable of, but it is done using handles, not file descriptors IIUC.
What did you see instead?
Parent process
fork/exec C:\Users\light\AppData\Local\Temp\2\go-build579847834\command-line-arguments\_obj\exe\foo.exe: not supported by windows
exit status 1
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 22 (15 by maintainers)
Commits related to this issue
- syscall: introduce SysProcAttr.AdditionalInheritedHandles on Windows This allows users to specify handles that they explicitly want to be inherited by the new process. These handles must already be m... — committed to golang/go by zx2c4 3 years ago
- make ExecAllocator use pipe connection by default Note that pipe connection is just supported on non-windows as of now. see https://github.com/golang/go/issues/21085. — committed to ZekeLu/chromedp by ZekeLu 3 years ago
- make ExecAllocator use pipe connection by default Note that pipe connection is just supported on non-windows as of now. see https://github.com/golang/go/issues/21085. — committed to ZekeLu/chromedp by ZekeLu 3 years ago
- make ExecAllocator use pipe connection by default Note that pipe connection is just supported on non-windows as of now. see https://github.com/golang/go/issues/21085. — committed to ZekeLu/chromedp by ZekeLu 3 years ago
I don’t think it is that simple. We use CreateProcess Windows API to start new process. CreateProcess has bInheritHandles parameter that controls which handles are inherited by the child process. Go syscall package sets bInheritHandles to true because it needs to pass stdin, stdout and stderr. But this makes all inheritable handles escaped into child process (see the doco https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx : “… If this parameter TRUE, each inheritable handle in the calling process is inherited by the new process. …”). We cannot allow that, so none of file handles inside Go are inheritable. We only make stdin, stdout and stderr for new child inheritable, just before we launch new process. We also have a lock that prevents us from running CreateProcess simultaneously, otherwise this would allow these 3 handles (potentially) end up in the wrong process.
What you are proposing - calling SetHandleInformation - will make that handle inheritable, and it can possibly escape into wrong process. We could use DuplicateHandle API instead (just before we launch the process), and then close new handle immediately. But DuplicateHandle will create new file handle with new handle number. How are you going to pass that number to the user of Cmd.ExtraFiles?
Not true. I could be wrong because I do not know much about Unix, but whatever file is in ExtraFiles[0] will have file handle of 3 in the child process, ExtraFiles[1] will be 4, and so on. So everyone knows how it works, and you don’t need to pass these numbers around.
Alex