pipe()和socket()线程安全吗? (双close()问题)

时间:2019-06-23 07:33:01

标签: linux c++11 thread-safety file-descriptor

我正在使用g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
uname -a Linux ubuntu 4.18.0-17-generic #18~18.04.1-Ubuntu SMP Fri Mar 15 15:27:12 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

我认为所有创建文件描述符的系统调用在Linux上都是线程安全的。 我的意思是,从不同的线程并行调用socket()pipe()不应返回 same fd。 是不是真的

2 个答案:

答案 0 :(得分:1)

在示例程序中,除了pIsI之外,每个全局变量上都有data races。您从一个线程读取它们,而从另一个线程写入它们。这会导致未定义的行为,这意味着从该程序获得的任何结果都是毫无意义的。

socketpipe函数都是线程安全的,并且可以从异步信号处理程序中安全使用。奇怪的是,手册页不包含这些信息,但是在线文档中包含。

答案 1 :(得分:0)

这不公平,因为我没有真正显示任何真实代码,但我想为其他用户回答自己的问题。

  • 我看到的症状是类似的错误
    • errno 9 (Bad file descriptor)
    • 应用程序死锁(由于与错误文件描述符上的其他进程通信)
  • 这是一个多线程环境。
  • 由于我为了调试添加了日志,我开始怀疑socket()pipe()是否不是多线程安全的。我同时看到两个不同线程使用的同一个fd(没有将日志放在所有相关位置,这就是为什么我看到这种奇怪的情况)。
  • 由于这段Double close(),我知道这是我的问题的一个变体:
    • 线程1 open() fd 100
    • 线程1 close() fd 100关闭#1 <---这是错误
    • 线程2 open() fd 100(现在完全正常,其中进程中的任何线程都没有使用100
    • 线程1 close() 再次 fd 100关闭#2。
      • 第二个close()实际上关闭了线程2的fd 100。然后,当线程2使用此fd时,它将使用封闭的fd得到errno 9 (Bad file descriptor)
      • 它也可能变得更加复杂:此刻fd 100已关闭。它可能会被另一个与read()/write()一起使用的线程重新打开。线程2也会与read()/write()一起使用它-在这种情况下,两个线程使用相同的fd是错误的,并使在该fd上发送/接收的数据无效。