【问题标题】:Linux write() crashes application if file descriptor is closed如果文件描述符关闭,Linux write() 会使应用程序崩溃
【发布时间】:2020-10-27 14:05:03
【问题描述】:

在我的 C++ 应用程序中,一个线程使用 poll() 函数在文件描述符打开、数据可供读取和 fd 关闭时得到通知。当数据可用时,它被读取并交付给其他线程进行处理和回复。事实上,另一方面,客户端在打开的套接字上等待同步回复。 当一个 fd 不再可用时,我尽最大努力通知其他线程,但不同步(目前)跨所有线程设置的文件描述符。 问题是这段代码:

while(bytes < len && d->ok) {
        w = write(fd, buf + bytes, len - bytes);
        d->ok = (w >= 0);
        if(d->ok)
            bytes += w;
    }
    

fd 关闭后整个应用程序崩溃。

预期行为:写入返回负数但没有崩溃。 我已经阅读了发送 SIGPIPE 的一些线程,这就是应用程序崩溃的原因,但我发现它没有明确记录在

人写

我想到的选项:

  • 同步文件描述符集,这样一旦 poll() 通知 fd 关闭,其他线程就不再使用它了
  • 使用 send() 而不是 write。

但是,我想,如果 fd 在我处于 write() while 循环时被另一端关闭,我会得到一个崩溃而不是 write() 的简单否定结果

我做错了什么? 感谢您的任何建议

【问题讨论】:

    标签: linux multithreading crash write


    【解决方案1】:

    I/O函数可能会导致SIGPIPE,数据写入越快,可能性越大。不幸的结果是您的应用程序只是崩溃而您没有机会处理错误,这确实可能非常令人困惑。要解决这个问题,您只需将 SIGPIPE 的信号处理程序设置为 SIG_IGN - 然后 write() 将改为返回 -1 并带有 errno=EPIPE(断管),您可以关闭侧面描述符并正确清理。

    【讨论】:

      【解决方案2】:

      如果文件描述符可以在一个线程中关闭,而另一个线程正在或可能正在使用它,那么您将永远无法让您的代码可靠地工作。您必须使用某种形式的同步。

      作为可能出错的一个示例,请考虑以下情况:

      1. 线程 A 关闭文件描述符 10,就像线程 B 即将write 一样。
      2. 在线程 B 可以写入之前,线程 C 打开并连接一个新的套接字,它恰好发生在描述符 10 中。
      3. 线程 B 终于开始执行,写入文件描述符 10,但现在这是线程 B 打开的新连接。

      糟糕,您只是将信息写入了错误的端点。我希望它不是安全敏感的。

      您必须确保一个线程不可能释放资源,而另一个线程正在或可能正在使用它,因为如果您不这样做,您将总是有一个可能的竞争条件,其中一个线程释放资源正确 另一个线程尝试访问它之前。这可能是灾难性的。

      【讨论】:

        猜你喜欢
        • 2022-01-11
        • 2013-01-06
        • 1970-01-01
        • 2017-06-20
        • 2018-04-21
        • 1970-01-01
        • 2017-09-05
        • 1970-01-01
        • 2015-05-20
        相关资源
        最近更新 更多