你正在使用的Go版本是什么( go version
)? 1.17.10
这个问题在最新版本中是否重现?没有测试,但最近没有与此相关的更改
你正在使用什么操作系统和处理器架构( go env
)? Windows amd64
你做了什么?
从 #48393 @alexbrainman
This commit (@zx2c4 )更改了Windows上的进程创建,使得只有stdin/stdout/stderr以及AdditionalInheritedHandles中列出的句柄可以被子进程继承。
不幸的是,这与我们使用的Python wrapper tool 交互得不好。这个 Package 器设置了一个包含所有必要软件包的虚拟环境,然后简单地向Python解释器发出命令。
一些调用者依赖于能够将文件句柄(即管道)传递给Python脚本。如果直接调用Python,这是可以正常工作的,但是由于对golang实现的这种更改,我们的 Package 器不再将这些句柄传递给Python子进程。
由于 Package 器不了解调用者希望传递的文件句柄,我们不能只是将它们添加到AdditionalInheritedHandles中。
你期望看到什么?
如果能以某种方式选择回到旧的行为,那就太好了,可以使用os/exec。
你看到了什么?
似乎没有办法回到旧的行为,除了在我们自己的代码中进行所有低级Windows调用之外。
谢谢,
8条答案
按热度按时间pobjuy321#
@brianryner8 感谢您创建这个问题。
您能否提供一个在1.17.10之前的小可运行示例,但现在不起作用?
谢谢。
Alex
9jyewag02#
#48393中的示例展示了这个问题。对我们来说,唯一的区别是,而不是在我们的Go应用程序中创建管道,当我们的Go二进制文件被执行时,它作为可继承的句柄传递。
bq3bfh9z3#
在#48393中的示例展示了这个问题。
我不认为这段代码有问题。这段代码只需要使用AdditionalInheritedHandles。Go 1.17添加了AdditionalInheritedHandles,现在如果你想在进程之间传递句柄,每个人都必须使用它。
Alex
u2nhd7ah4#
完全抛开这个变化破坏了 go1compat (在我看来,这本身就足以成为改变默认行为回退到先前行为的理由),在这种情况下的问题是,这里的 Go 程序 不知道 应该传播哪些句柄,因此没有简单的方法来设置 AdditionalInheritedHandles。
流程如下:
在 Go 1.16 中,这工作得很好。在 Go 1.17 中,我们不得不复制 exec_windows.go(https://chromium-review.googlesource.com/c/infra/luci/luci-go/+/3739699) 的很大一部分。
提供一个函数可能是合理的妥协,让程序可以调用该函数,用旧版本中存在的任何句柄填充 AdditionalInheritedHandles(尽管,再次强调,这违背了 go1compat...但至少它不会让用户陷入困境)。
u4dcyp6a5#
感谢您的评论。
完全抛开这个改变破坏了 go1compat 的问题,您的程序假设 syscall.StartProcess 会将所有可继承的句柄传递给新进程,但我认为这是 Go 1.16 中的一个 bug。我会让 Go 团队解决我们的分歧。
在这种情况下的问题是,Go 程序在这里 不知道 应该传播哪些句柄,所以没有简单的方法来设置 AdditionalInheritedHandles。
我同意。您的程序设计假设可继承的句柄会被传递给子进程。
在 Go 1.16 中,这没问题。在 Go 1.17 中,我们不得不复制 exec_windows.go 的一大块内容(https://chromium-review.googlesource.com/c/infra/luci/luci-go/+/3739699)。
我很抱歉您不得不为您的程序添加额外的代码。但也许这是一个足够好的解决方案。您是第一个抱怨这个改变的人。也许 Go 需要为像您这样的用户提供一些通用解决方案。我不知道。
提供一个函数可能是一个合理的妥协,该程序可以调用该函数来填充 AdditionalInheritedHandles,其中包含旧版本中可能存在的任何句柄
我不知道如何枚举所有可继承的进程句柄。也许其他人有一些建议。
Alex
9njqaruj6#
@riannucci
Completely setting aside that this change breaks go1compat
There are no guarantees on the syscall package:
It is impossible to guarantee long-term compatibility with operating system interfaces, which are changed by outside parties. The syscall package is therefore outside the purview of the guarantees made here.
u7up0aaq7#
无法保证与操作系统接口的长期兼容性,这些接口会被外部方更改。因此,syscall包不在本保证范围内。
虽然确实如此,操作系统接口会被外部方更改,
1.但这种对系统调用行为的变化似乎并非由底层Windows API的破坏性更改所引发
1.这种变化表现为os/exec包(即Cmd.Start/Cmd.Run)的行为更改,这将是go1compat保证的一部分,不是吗?
ct2axkht8#
我不了解任何合理的方法来检索所有继承的进程句柄,因此
os
和syscall
目前都无法支持 @riannucci 在 #53652(评论)中描述的流程。我认为这个用例非常有效,我们应该提供一种启用它的方法。我的建议是选择旧的行为,即拥有一个全局锁来保护进程创建,并且不要明确指定要由进程继承的句柄列表。用户可以通过设置一个名为
InheritAllInheritableHandles
的 syscall.SysProcAttr 属性来选择这种行为:我会提交一个新的提案问题,因为这会添加一个新的API。