java - 关于阻塞系统调用和潜在的竞争条件
问题描述
我们对网络套接字使用阻塞系统 I/O 调用。我们想要的行为是当close()
在socket上调用时,阻塞调用需要返回并抛出异常(reference),
查看 OpenJDK,这就是它的实现方式。它使用用户信号来唤醒阻塞线程。相应的信号处理程序是No-OP。在阻塞调用之前,它会注册可能被阻塞的线程。当文件描述符关闭时,关闭线程会向阻塞的 I/O 线程发送一个信号,这会导致阻塞调用返回EINTR
。
但是,我仍然认为以下代码块源中存在潜在的竞争条件:
startOp(fdEntry, &self); // (1)
ret = FUNC; // (2)
endOp(fdEntry, &self);
在I/O线程中,(1)执行,然后关闭线程调用close
并发送信号给(2)开始执行之前的I/O线程。信号被接收并丢弃。当 (2) 开始在 I/O 线程中执行时,它会进行阻塞系统调用。在这个阶段,fdEntry 可能已关闭,或者即将关闭。
我理解正确吗?我是否做出了错误的观察,或者竞争条件的可能性很低,所以我们可以放心地忽略它?
解决方案
回答自己:事实证明这确实是一个错误。修复就在close
一边:我们首先关闭文件描述符,然后向阻塞线程发出信号。如果阻塞线程错过信号并启动阻塞调用,它将立即返回,EBADF
因为文件描述符已关闭。
推荐阅读
- c++ - 使用 cmake 的 GoogleTest:将测试分成 .cpp 和 .h 文件
- windows - 从文件名中删除和添加字符的命令行 - Windows
- r - igraph中多个有向图的分类
- scala - 如何将类型 Any List 转换为类型 Double (Scala)
- c# - C#:具有未知签名的通用方法表达式
- php - 在保持结构的同时对多维数组中特定键的值求和
- python-3.x - 如何创建一个可迭代的类
- python - 在列表列表中搜索和替换完全匹配的单词
- ansible - 如何解决警告“无法匹配提供的主机模式,忽略:
? - api - findOne 函数在此代码中不起作用