【问题标题】:Send CTRL+C to subprocess tree on Windows将 CTRL+C 发送到 Windows 上的子进程树
【发布时间】: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


    【解决方案1】:

    我不知道管理/重定向标准输入等。 al.,但用于管理子进程树 您是否考虑过使用 Windows Job Objects api?

    还有其他几个关于管理流程树的问题 (How do I automatically destroy child processes in Windows?Performing equivalent of “Kill Process Tree” in c++ on windows),如果可以使用它,它看起来是最干净的方法。

    Windows Via C/C++ by Jeffery Richter 的第 5 章对使用 CreateJobObject 和相关 API 进行了很好的讨论。

    【讨论】:

    • 我之前研究过作业对象,但它们提供的停止作业的唯一机制是强制终止其进程。我想发送 CTRL+C 的原因是让进程有机会干净地完成。请注意,如果我不关心专门发送 CTRL+C,进程组和 CTRL_BREAK_EVENT 会做得令人满意。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-02
    • 1970-01-01
    • 2010-09-21
    相关资源
    最近更新 更多