写入`stderr`时冻结

时间:2016-05-23 08:07:46

标签: c linux freeze stderr

在我的程序中,在这种情况下写入stderr时有时会冻结:

  1. 程序启动(例如从终端开始)
  2. 程序自行分叉两次并使用execvp以不同参数启动每个进程(原始文件从/proc/self/exe读取)
  3. 第一个启动的程序退出。
  4. 现在两个分叉进程仍在运行
  5. 关闭第一个程序启动的终端
  6. 使用fprintf写一些stderr作品的尝试,在某些时候我将完全锁定我的程序。调试器告诉我它的fprintf。
  7. 这里发生了什么?我已经尝试过将SIG_IGN放在SIGPIPE上,以防止程序在没有人再听管道时崩溃。但是现在我被卡住了(冻结的行为与SIG_IGN相同,没有它)。

    感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

简而言之:系统发送程序信号以避免出现问题。你忽略了这些信号。坏事发生了。

当你的父程序运行时,它有stdin(fd 0),stdout(fd 1)和stderr(fd 2)连接到运行你的shell(终端)的TTY。这些功能很像管道。关闭终端时,这些fds会悬空,另一侧没有人可以与他们通信。

起初,没有任何不好的事情发生。您写入stderr,标准库缓存这些写入。没有系统调用,所以没问题。

然后填充缓冲区,stdlib尝试刷新它们。当它这样做时,它会填充管道或TTY的内核缓冲区。起初,这也很好。然而,迟早,这些缓冲区也会填满。当发生这种情况时,内核会暂停您的进程并等待某人从这些管道的另一端读取。但是,由于您关闭了终端,所以没有人会这样做,并且您的程序会被无限期暂停。

避免此问题的标准方法是断开0-2文件描述符与控制TTY的连接。而不是告诉你如何做到这一点,我想建议你在这里尝试做什么,运行一个程序,以便它完全与TTY断开连接,有一个名字:daemonizing。

查看this问题,了解有关如何执行此操作的详细信息。

已编辑添加:

您的功能尚不清楚您execve的节目是否是您自己的节目。如果不是,请注意许多用户程序不是作为守护程序运行的。最明显的警告是,如果未连接到任何TTY的程序打开TTY文件,并且除非它将O_NOCTTY传递给open,则该TTY将成为程序的控制TTY。视情况而定,可能会导致意外结果。