read() 挂在僵尸进程上

read() hangs on zombie process

我有一个 while 循环,通过将子进程的 stdout 重定向到父进程,使用阻塞 I/O 从子进程读取数据。通常,一旦子进程退出,阻塞 read() 在这种情况下将 return 因为从中读取的管道已被子进程关闭。

现在我有一个案例,其中 read() 调用不会为完成的子进程退出。子进程最终处于僵尸状态,因为操作系统正在等待我的代码获取它,但我的代码却阻塞在 read() 调用上。

子进程本身在挂起时没有任何子进程 运行ning,而且我在查看 /proc/<child process PID>/fd 时没有看到列出任何文件描述符。然而,子进程确实 fork 了两个守护进程,其目的似乎是监视子进程(子进程是我无法控制的专有应用程序,因此很难确定)。

当从终端 运行 时,我尝试 read() 从中退出的子进程自动退出,然后它派生的守护进程也终止。

Linux 版本为 4.19.2.

在这种情况下,read() 未 return 的原因可能是什么?

跟进:

The child process did however fork two daemon processes ... What could be the reason of read() not returning in this case?

分叉进程在子进程终止时仍然打开文件描述符。因此 read 从不调用 returns 0.

那些守护进程应该关闭所有文件描述符并打开文件进行日志记录。

read(2) 在死管 child 上阻塞的一个可能原因(最常见)是 parent 没有关闭管道的写入端,所以该管道仍然有一个开放的(用于写入)描述符。在读取之前关闭 parent 进程中管道的写入端。 child 死了(你说的是僵尸)所以 它不可能是管道写入端打开的进程 。并且不要忘记 wait(2) 为 parent 中的 child,否则你会得到一个充满僵尸的系统 :)

记住,您必须在代码中执行两次关闭操作:

  • 一个在parent进程中,关闭管道的写端,留下parent进程只有一个读描述符。

  • child进程中的一个(就在exec(2)ing之前)关闭管道的读取端,只留下一个写描述符的child进程.

如果您想使用pipe(2)向child发送信息,请在以上两点中将读取更改为写入,反之亦然。