【发布时间】:2009-11-25 17:54:14
【问题描述】:
我想运行任意基于控制台的子进程并从单个主进程管理它们。基于控制台的子进程通过标准输入、标准输出和标准错误进行通信,如果您在真正的控制台中运行它们,它们会在您按 CTRL+C 时干净地终止。其中一些实际上可能是进程树,例如运行可执行文件的批处理脚本,该可执行文件又可能运行另一个可执行文件来完成某些工作。我想重定向他们的标准 I/O(例如,以便我可以在 GUI 窗口中显示他们的输出)并在某些情况下向他们发送 CTRL+C 事件,以便他们放弃并干净地终止。
下面两张图首先展示了正常的结构——一个主进程有四个worker子进程,其中一些worker有自己的子进程;然后当需要停止其中一名工作人员时应该发生什么 - 它及其所有子进程都应该收到 CTRL+C 事件,但没有其他进程应该收到 CTRL+C 事件。 p>
(来源:livejournal.com)
此外,我更希望没有额外的窗口对用户可见。
这是我尝试过的(请注意,我正在使用 Python,但 C 的解决方案仍然会有所帮助):
- 使用
CREATE_NEW_CONSOLE生成一个额外的中间进程,然后让它生成工作进程。然后在我们想要杀死工人时调用GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)。不幸的是,CREATE_NEW_CONSOLE似乎阻止我重定向标准 I/O 通道,所以我没有简单的方法将输出返回到主程序。 - 使用
CREATE_NEW_PROCESS_GROUP生成一个额外的中间进程,然后让它生成工作进程。然后在我们想要杀死工人时调用GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)。不知何故,这设法将 CTRL+C only 发送到主进程,这完全没用。仔细观察,GenerateConsoleCtrlEvent 说 CTRL+C 不能发送到进程组。 - 使用
CREATE_NEW_PROCESS_GROUP生成子进程。然后调用GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid) 杀死worker。这并不理想,因为 CTRL+BREAK 不如 CTRL+C 友好,并且可能会导致更混乱的终止。 (例如,如果它是一个 Python 进程,则不会捕获任何 KeyboardInterrupt 并且不会运行 finally 块。)
有什么好方法可以做我想做的事吗?我可以看到我可以理论上在第一次尝试的基础上构建并找到其他方式在进程之间进行通信,但我担心它会变得非常尴尬。是否有其他程序可以达到相同效果的好例子?它看起来如此简单,以至于它不可能是一个不常见的要求。
【问题讨论】:
标签: windows