0

在我的 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() 的简单否定结果

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

4

2 回答 2

0

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

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

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

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

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

于 2020-10-05T21:02:28.197 回答
0

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

于 2020-10-05T16:48:44.847 回答