关于阻止系统调用和潜在的比赛条件



我们对网络套接字使用阻塞系统I/O调用。我们想要的行为是,当在套接字上调用close()时,阻塞调用需要返回并抛出异常(引用(,

看看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可能已经关闭,或者即将关闭。

我理解正确吗?我的观察是错误的,还是比赛条件的可能性很低,所以我们可以安全地忽略它?

回答我自己:事实证明这确实是一个bug。修复是在close方面:我们首先关闭文件描述符,然后向阻塞线程发出信号。如果阻塞线程错过信号并启动阻塞调用,它将立即返回EBADF,因为文件描述符已关闭。

最新更新