【问题标题】:waiting for a background process to terminate while running a foreground process在运行前台进程时等待后台进程终止
【发布时间】:2015-10-31 15:13:20
【问题描述】:

我的 shell 中安装了一个 SIGCHILD 处理程序。假设我正在使用 waitpid 来等待前台进程终止,以便我可以收获它。

据我所知,waitpid 暂停当前进程并等待给定进程终止,是吗?

如果我的 shell 正在等待前台进程时其中一个后台进程终止了怎么办?我的 shell 什么时候会收到终止的后台进程?我怎样才能确保后台进程会立即被收割?

【问题讨论】:

    标签: c operating-system signals


    【解决方案1】:

    只需让您的父 shell 循环等待任何死去的孩子,当 waitpid() 返回时,您分析该孩子死后该怎么做。

    int status;
    int corpse;
    
    while ((corpse = waitpid(-1, &status, 0)) != -1)
    {
        …perform post-mortem actions…
    } 
    
    • 如果前台进程终止(已完成),您将继续提示输入下一个命令。
    • 如果后台进程死了,您会注意到它已经消失,也许记录下它的状态,然后返回到另一个循环循环。

    当前台进程退出时,您将在发出下一个提示之前报告所有死亡的孩子。

    您永远不应该因为 -1 值而退出该循环。

    【讨论】:

    • 如果您在循环中等待,您可能需要使用WNOHANG
    • @EOF:我不希望我的 shell 在前台进程运行时处于忙碌状态。在这个阶段,我知道我正在等待前台进程完成。任何死亡的后台进程也需要部署,但它们是巧合。我希望 shell 休眠直到进程终止;我不想要 WNOHANG。如果我检查是否任何进程已经死亡,情况会有所不同;然后我会使用 WNOHANG。在这里,上下文显式地等待进程终止并且 WNOHANG 不正确。如果检查“是否”,用-1退出循环是可行的(没有任何孩子离开)。
    • 如果一个 BG 进程终止,而父 shell 正在运行一个 FG 进程,我不能等待 FG 进程终止;我需要立即收获 BG 进程。这可能吗?
    • @JonathanLeffler:嗯,你最终需要WNOHANG等待,对于在你等待的前台进程之后终止的任何后台进程。跨度>
    • @ReiJinThunderKeg:整个答案都说“是”并展示了如何做到这一点。