【问题标题】:How to avoid zombie processes after executing them in background如何在后台执行僵尸进程后避免它们
【发布时间】:2010-05-21 10:01:32
【问题描述】:

我们正在用 C 语言编写类似 bash 的 shell,但后台进程存在问题。 问题是父进程在没有&的情况下等待子进程,我们为SIGCHLD制作了一个signal_handler,里面有一个等待。

我们要避免的主要问题是:signal_handler总是执行(有后台进程和前台进程),所以如果signal_handler在父进程之前捕获到SIGCHLD,则父进程的等待没有子进程等待,所以返回一个错误。

我们取决于他们之前执行过谁,并且我们希望如果没有 & signal_handler 等待不会在父亲之前收集孩子。

任何帮助都至关重要。提前非常感谢。

【问题讨论】:

  • 设置“父亲”进程除了检查终止的子进程之外什么都不做。从而降低出现裂缝的可能性。您应该在 cild 进程中完成所有工作。

标签: c shell background


【解决方案1】:

你的问题对我来说有点不清楚,但我会提到一些我考虑过针对类似情况做的事情。

当您创建一个进程时,您可以暂时阻止SIGCHLD 并将子进程的记录(以及如何处理它)放入一个表中。

child_table_node_t * node = malloc(sizeof(child_table_node_t) );
// err check that
child_table_node_init(node, type_of_child_stuff);

sigset_t old, set;

sigemptyset(&set);
sigaddset(&set, SIGCHLD);
sigprocmask(SIG_BLOCK, &set, &old);
pid_t pid = fork();
if (pid > 0) {
   node->pid = pid;
   add_to_table(alive_children, node);
   sigprocmask(SIG_SETMASK, &old, NULL);
   // other stuff
} else {
   sigprocmask(SIG_SETMASK, &old, NULL);
   if (!pid) {
       // do child stuff
   } else {
       // do parent with no child stuff
   }
}

然后您的handle_sigchild 可以查找表中死亡(或停止或其他)的孩子并为他们做点什么。我建议将它们从alive_children 表中删除,并在它们死亡时将它们放入信号处理程序的dead_children 表中,以便您的应用程序可以更轻松地处理它们并释放它们的内存。如果您想跟上孩子们被阻止和死亡的步伐,那么这将变得有点复杂 b/c 您不会希望将它们从活动表中删除。仅在非信号代码中遍历表以定位更改的节点可能更容易。如果是这种情况,您可以在不阻塞信号的情况下执行此操作,除非您添加或删除了节点。

然后,您的应用程序可以根据存储在该进程的表节点中的数据执行特定于死去的孩子的操作。如果孩子在前台,那么它的死亡(或停止动作)将是将退出代码存储到退出代码变量中并再次开始从终端或脚本中获取命令。如果新死的孩子是后台进程,那么您只需记录其退出代码并在下次打印命令提示符之前将其报告给终端(如果您处于交互模式)。

【讨论】:

  • 您的建议非常有用。我们最后制作了一个数组来存储后台进程的 pid,以便在 signal_handler 中只等待这些 PID。我们非常感谢您的回答;)。
  • 我很高兴它有帮助。祝你的项目好运:-)
猜你喜欢
  • 2011-09-20
  • 1970-01-01
  • 2017-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-02
  • 2019-12-31
相关资源
最近更新 更多