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

Most upvoted comments

if SetHandleInformation enables inheriting handles, would it make sense to amend the behavior of ExtraFiles on Windows to set this option on all the file handles in the ExtraFiles slice?

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?

ExtraFiles already requires some arrangement with the child process on Unix systems

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