pipe() 和 socket() 线程安全吗? (双重关闭()问题)
Are pipe() and socket() thread safe? (double close() problem)
我正在使用 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()
不应该 return 相同 fd。
是不是真的?
在您的示例程序中,除了 pI
和 sI
之外,每个全局变量都有 data races。您从一个线程读取它们,同时从另一个线程写入它们。这会导致未定义的行为,这意味着您从该程序获得的任何结果都是无意义的。
两个 socket
and the pipe
函数都是 thread-safe,并且可以安全地从异步信号处理程序中使用。奇怪的是,手册页不包含这些信息,但联机文档包含。
这不太公平,因为我没有真正展示任何真实代码,但为了其他用户,我想回答我自己的问题。
- 我看到的症状是像这样的错误
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的fd100
,那么当线程2使用这个fd时,它会得到errno 9 (Bad file descriptor)
使用关闭的fd。
- 它也可能变得更复杂:此时 fd
100
被关闭。它可能被另一个与 read()/write()
一起使用的线程 re-opened。线程 2 也会将它与 read()/write()
一起使用 - 这种情况下,两个线程使用相同的 fd 是错误的,并且会使该 fd 上的数据 sent/received 无效。
我正在使用 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()
不应该 return 相同 fd。
是不是真的?
在您的示例程序中,除了 pI
和 sI
之外,每个全局变量都有 data races。您从一个线程读取它们,同时从另一个线程写入它们。这会导致未定义的行为,这意味着您从该程序获得的任何结果都是无意义的。
两个 socket
and the pipe
函数都是 thread-safe,并且可以安全地从异步信号处理程序中使用。奇怪的是,手册页不包含这些信息,但联机文档包含。
这不太公平,因为我没有真正展示任何真实代码,但为了其他用户,我想回答我自己的问题。
- 我看到的症状是像这样的错误
errno 9 (Bad file descriptor)
- 应用程序死锁(由于在错误的文件描述符上与其他进程通信)
- 这是一个多线程环境。
- 由于我为了调试而添加的日志,我开始怀疑
socket()
和pipe()
不是多线程安全的。我看到两个不同的线程同时使用同一个 fd(我没有把日志放在所有相关的地方,这就是为什么我看到这个奇怪的事件)。 - 多亏了这个 Double close() 段落,我明白这是我的问题的变体:
- 线程 1
open()
fd100
- 线程 1
close()
fd100
。 关闭 #1 <--- 这是错误 - 线程 2
open()
fd100
(现在完全没问题,进程中的任何线程都没有使用100
) - 线程 1
close()
再次 fd100
。 关闭#2。- 这秒
close()
实际上关闭了线程2的fd100
,那么当线程2使用这个fd时,它会得到errno 9 (Bad file descriptor)
使用关闭的fd。 - 它也可能变得更复杂:此时 fd
100
被关闭。它可能被另一个与read()/write()
一起使用的线程 re-opened。线程 2 也会将它与read()/write()
一起使用 - 这种情况下,两个线程使用相同的 fd 是错误的,并且会使该 fd 上的数据 sent/received 无效。
- 这秒
- 线程 1