在库中的write(2)调用上禁用SIGPIPE信号

Clo*_*oud 5 c linux signals pipe sigpipe

是否可以SIGPIPE在写入pipe()FD 时禁用信号的提升(),而无需安装我自己的信号处理程序或全局禁用/屏蔽信号?


背景

我正在一个小的库中工作,该库偶尔会创建一个管道,以及fork()一个临时的子进程,该进程等待父进程的消息。当子进程接收到来自父进程的消息时,它(有意地)死亡。


问题

在我无法控制的情况下,子进程会从另一个易于崩溃的(第三方)库中运行代码,因此在我write()连接到管道之前,我无法始终确定子进程是否处于活动状态。

这导致我有时尝试write()使用子进程的末端已经死掉/已关闭的管道,并SIGPIPE在父进程中引发a 。我在其他客户将要使用的库中,因此我的库必须是自包含的,并且对调用应用程序尽可能透明。安装自定义信号处理程序可能会破坏客户的代码。


到目前为止工作

通过使用setsockopt(..., MSG_NOSIGNAL),我已经解决了套接字的这个问题,但是找不到与管道在功能上等效的东西。我已经看过临时安装一个信号处理程序以捕获SIGPIPE,但是我看不出有任何方法将其范围限制在我的库中而不是整个过程中(而不是原子的)调用函数中。

我在SO上也发现了一个类似的问题,在问同样的事情,但是不幸的是,使用poll()/ select()不会是原子的,并且子进程在我select()write()调用之间死亡的可能性很小(但有可能)。


问题(redux)

有什么方法可以完成我在这里尝试的工作,或者原子地检查并写入管道,而不会触发将生成该行为的行为SIGPIPE吗?另外,是否有可能做到这一点知道子进程是否崩溃?知道它是否崩溃可以让我为提供“疯狂”库的供应商建立案例,并让他们知道它经常失败。

Clo*_*oud 1

在尝试了所有可能的方法来解决这个问题之后,我发现只有两个方法可以解决这个问题:

  • 使用socketpair(PF_LOCAL, SOCK_STREAM, 0, fd), 代替管道。
  • 创建一个“牺牲”子进程,如果引发,fork()则允许通过该子进程崩溃。SIGPIPE

我走了那socketpair条路。我不想这样做,因为它涉及重写相当多的管道逻辑,但这并不太痛苦。

谢谢!