我有一个奇怪的情况。
我有一个用 C 编写的程序“A”,它以其他可执行文件的名称作为参数,例如“B”、“C”、“D”等。“A”的主要工作是分叉并启动“B” 、“C”等,然后检查它们是否崩溃,在这种情况下重新启动崩溃的进程。
此外,进程“A”运行一个单独的线程用于 RTC 同步目的。 “A” 开头为/bin/sh -c A B C D etc
。
我在嵌入式环境中,并且使用源自 Linux 4.4.57 的定制内核。
现在问题来了:有时我的进程“A”会变成僵尸!
我的一些观察:
- 启动“A”的父进程
/bin/sh -c
仍然存在; - 子进程“B”、“C”等均未死亡;
- “A”对信号做出反应;
- 如果我杀死父进程
/bin/sh -c
,“A”的父进程将变为 init (1),但该进程仍然是僵尸进程; - 杀死僵尸“A”的唯一方法是发出
kill -9 «pid-of-A»
; - RTC 同步线程仍在运行!;
现在,由于“A”响应信号并且内部线程仍在运行,这个僵尸进程快要把我逼疯了。
如何解释这种行为?可能与内核构建配置有关?
编辑:我仔细查看了代码,发现“A”是使用以下命令作为守护进程启动的:
start-stop-daemon -b --start --quiet --pidfile /var/run/A.pid --background --exec /bin/sh -- -c "A B C D > /var/log/log 2>&1"
更新:我已经能够通过调用 pthread_exit() 来复制相同的行为。问题是我在原始源上找不到任何对 phread_exit 的引用。主线程是否有其他方法可以停止让所有其他线程保持活动状态?
答案1
僵尸进程是一个已完成的进程,但在进程表中仍然有一个条目,因为例如它的子进程仍然活着(请参阅维基百科)。
所以,如你所说,如果B、C、D都没有死,而A执行完毕,那么它将成为僵尸,直到B、C、D也都执行完毕。
这是正常行为。
所以这看起来像是 A 中的一个错误:当它的孩子还活着时,它不应该死,因为它应该监视孩子。修复A的bug,不用担心它变成僵尸了。
答案2
pthread_exit()
如果您在函数中使用main()
,这个帖子表明主线程可能进入僵尸状态,但其他线程继续运行。由于召唤pthread_exit()
是main()
完全合法的,我认为这是正常情况,而且这个特殊的不死生物是无害的。您可以忽略它,或者等待其他线程main()
而不是在pthread_exit()
那里使用。
答案3
我通过查看 dmesg 找到了问题和问题的解决方案:我发现有一个“内部错误:哎呀:817 [#1] ARM”,是由 proc 文件中的自定义内核函数引起的。 proc文件被成为僵尸的进程的主线程读取,有时这个操作导致主线程死掉......这与@muru的答案完全相同。我修复了该功能,现在该进程不再终止。无论如何,谢谢大家。