BSc*_*ker 11 c shell sudo exec sigchld
我目前正在编写shell.我执行进程并利用SIGCHLD信号处理程序在它们完成时清理(等待它们).
一切都在工作 - 除非我执行升级权限的进程sudo.在这些情况下,我从来没有得到过SIGCHLD信号 - 所以我永远不知道这个过程已经完成了.
当我收到诸如此类的命令时sudo ls,我执行程序sudo然后提供ls参数.我执行此执行execvp.
如果我在ps -auxshell执行后看一下sudo ls,我会看到以下内容:
root 4795 0.0 0.0 4496 1160 pts/29 S+ 16:51 0:00 sudo ls
root 4796 0.0 0.0 0 0 pts/29 Z+ 16:51 0:00 [ls] <defunct>
Run Code Online (Sandbox Code Playgroud)
因此,sudo在分配pid = 4795了孩子(ls)的情况下,跑步和分配4796.孩子已完成任务,现在正处于一个僵尸状态.sudo似乎并不想收获僵尸进程而只是坐在那里.
我想知道是什么原因造成这种现象-我已经尝试了不同的技术来清除这些僵尸进程,比如下运行我的壳sudo和等待直接sudo和PID其sudo执行(在上面的例子中4796).这些技术都没有奏效.
一如既往,任何建议都表示赞赏.
我的第一个想法是信号处理不正确,但您的帖子中没有足够的信息来编写测试代码来复制您的故障。但我可以给你一些地方可以看看。如果我为未来的读者介绍一些您已经了解的信号基础知识,请原谅我。
首先,我不知道您是否使用旧的 signal() 还是新的 POSIX sigaction() 信号例程来捕获信号。sigset() 是 GNU 中的一个有用的工具。
传统信号——signal()
在所有环境中使用原始信号处理器来保证信号处理器的密封性,即使不是不可能,也几乎是不可能的。
while( ( pid = waitpid( -1, &signal, WNOHANG ) ) > 0 )循环,直到找不到更多信号,因为遗留信号设置了一个布尔条件,指示至少有一个信号未完成。实际人数未知。
建议,捂住鼻子,逃离遗留信号。
遗留处理程序中缺少 while() 循环和多个 SIGCHILD,其中一个来自您的 sudo,一个或多个来自 sudo 引发的意外孙子。如果当孙子信号首先到来时只处理一个 SIGCHILD,则预期程序的信号将不会被捕获。
POSIX 信号——sigaction()
POSIX 信号可以清除旧信号的所有故障。
缺少掩码可能会导致奇怪的事情,例如如果您在 SIGCHILD 处理程序中收到 SIGCHILD,则丢失信号的跟踪。
GNU -- sigset()
GNU 提供了一个有用的中间函数,它具有与 signal() 相同的调用签名,但消除了大部分问题。还提供一些附加控制功能。使用 sigset() 可以轻松解决许多信号问题。
提醒
将信号处理程序视为程序中的线程,即使您没有在代码中使用线程。
在过去,您需要在信号处理程序中进行绝对最少的处理...无需调用具有副作用的库代码,例如 printf。当必须使用旧的信号处理程序时,我仍然遵循这一点,并且始终在新的处理程序中使用多线程警告。