-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
os/exec: No longer possible to pass all inheritable file handles to subprocess on Windows #53652
Comments
@brianryner8 thank you for creating the issue. Can you please provide a small self runnable example that worked before go 1.17.10 but does not work now? Thank you. Alex |
The sample in #48393 demonstrates the issue. The only difference for us is that rather than creating the pipe in our Go application, it is passed as an inheritable handle when our Go binary is executed. |
I don't see a problem with that code. That code just need to use AdditionalInheritedHandles now. Go 1.17 added AdditionalInheritedHandles, and now everyone have to use it if you want to pass handles between processes. Alex |
Completely setting aside that this change breaks go1compat (which, imo, should be sufficient reason BY ITSELF to change the default behavior back to the previous behavior), the problem in this case is that the Go program here does not know which handles should be propagated and so has no easy way to set AdditionalInheritedHandles. The flow goes:
In Go 1.16, this worked fine. In Go 1.17 we have to resort to duplicating a sizable chunk of exec_windows.go (https://chromium-review.googlesource.com/c/infra/luci/luci-go/+/3739699). It may be a reasonable compromise to provide a function which the program can call that populates AdditionalInheritedHandles with any Handles that would have been present in the older version (though, again, this goes against go1compat... but at least it wouldn't leave users high and dry). |
@riannucci thanks for your comments.
Your program assumed that syscall.StartProcess will pass all inheritable handles to the new process, but I consider that is a bug in Go 1.16. I will let Go team resolve our differences.
I agree. Your program design assumes that inheritable handles will by passed to the child process.
I am sorry you had to add extra code to your program. But perhaps it is a good enough solution here. You were the first to complain about this change. Perhaps Go need to provide some general solution for users like yourself. I don't know.
I don't know of a way to enumerate all inheritable process handles. Perhaps others have some suggestions. Alex |
There are no guarantees on the syscall package:
|
While it's certainly true that OS interfaces are changed by outside parties,
|
I'm not aware of any reasonable way to retrieve all the process inherited handles, therefore neither My proposal is to opt-in to the old behavior, that is having a global lock that guards process creation and don't explicitly specify the list of handles to be inherited by the process. Users could opt-in to this behavior by setting a syscall.SysProcAttr property, named type SysProcAttr struct {
// ...
NoInheritHandles bool // if set, each inheritable handle in the calling process is not inherited by the new process
AdditionalInheritedHandles []Handle // a list of additional handles, already marked as inheritable, that will be inherited by the new process
ParentProcess Handle // if non-zero, the new process regards the process given by this handle as its parent process, and AdditionalInheritedHandles, if set, should exist in this parent process
// New!
InheritAllInheritableHandles bool // if set and NoInheritHandles is unset, each inheritable handle in the calling process is inherited by the new process
} I'll submit a new proposal issue as this is adding a new API. |
What version of Go are you using (
go version
)? 1.17.10Does this issue reproduce with the latest release? not tested, but there are no recent changes related to this
What operating system and processor architecture are you using (
go env
)? windows amd64What did you do?
Spun off from #48393 @alexbrainman
This commit (@zx2c4 ) changed process creation on Windows so that only stdin/stdout/stderr, and the handles listed in AdditionalInheritedHandles, can be inherited by subprocesses.
Unfortunately, this interacts badly with a python wrapper tool we use. This wrapper sets up a virtual environment with all necessary packages, then simply shells out to the Python interpreter.
Some callers rely on being able to pass a file handle (i.e. a pipe) through to the Python script. This works fine if Python is invoked directly, but with this change to the golang implementation, our wrapper no longer passes these handles through to the python subprocess.
As the wrapper has no specific knowledge of the file handles that the caller wants to pass through, we can't just add them to AdditionalInheritedHandles.
What did you expect to see?
It would be nice if we could opt back into the old behavior in some way, using os/exec.
What did you see instead?
There doesn't seem to be a way to go back to the old behavior, other than by making all of the low-level Windows calls in our own code.
Thanks,
The text was updated successfully, but these errors were encountered: