【发布时间】:2013-09-27 20:33:51
【问题描述】:
我有一个由其父进程监控的进程。孩子遇到一个错误,导致它调用abort。该进程不会篡改中止进程,因此它应该按预期进行(转储核心,终止)。父母应该检测到孩子的终止并触发一系列事件来响应失败。子进程是多线程且复杂的。
这是我从ps看到的:
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
0 1000 4929 1272 20 0 85440 6792 wait S+ pts/2 0:00 rxd
1 1000 4930 4929 20 0 0 0 exit Zl+ pts/2 38:21 [rxd] <defunct>
所以孩子 (4930) 已经终止。这是一个僵尸。正如预期的那样,我无法附加到它。但是,父级 (4929) 仍被阻止:
int i;
// ...
waitpid (-1, &i, 0);
所以看起来孩子是一个僵尸,但不知何故还没有完成它的父母收割它所需的一切。我认为exit 的WCHAN 字段是一个有价值的线索。
平台为 64 位 Linux,Ubuntu 13.04,内核 3.8.0-30。孩子似乎没有倾倒核心或做任何事情。我已经离开系统几分钟,没有任何变化。
有没有人知道可能是什么原因造成的,或者我能做些什么?
更新:另一个有趣的信息——如果我kill -9父进程,子进程就会消失。这有点令人费解,因为父进程是微不足道的,只是阻塞在waitpid 中。另外,当这个问题发生时,我没有得到任何核心转储(来自孩子)。
更新: 孩子似乎被困在schedule,从exit_mm 调用,从do_exit 调用。我想知道为什么exit_mm 会打电话给schedule。我想知道为什么杀死父母会解开它。
【问题讨论】:
-
什么给了你
ps -eo wchan,pid | grep 4930? -
WCHAN字段在上面。孩子在exit,父母在wait。相信孩子莫名其妙卡在内核的exit函数中,无法完成完全终止的过程。 -
哦,是的,我现在明白了。您是否在子进程中使用信号处理程序?可能是它在退出期间挂在阻塞 IO 上吗?很高兴看到孩子的代码,但你说它太复杂了..没有机会把它分解成更简单的代码?
-
@hek2mgl 我无法在简单的条件下复制它。我想它有可能挂在 I/O 上,但是在映射消失后内核会在
exit上做什么 I/O?我们确实使用了信号处理程序,但是对std::_exit的调用已经发生并且内核已经接管了终止进程(因为该进程是僵尸进程,我们知道它没有运行任何用户空间代码)。 -
你能用其他内核重现它吗? (其他发行版,自编译,...)?