gpt4 book ai didi

java - JDK问题: interrupt another thread blocked on an IO operation with signal may fail

转载 作者:太空宇宙 更新时间:2023-11-04 11:57:33 26 4
gpt4 key购买 nike

OpenJDK 实现(linux 部分)大量使用信号来中断在 native IO 操作上阻塞的另一个线程。基本思想是,向目标线程发送唤醒信号将导致阻塞 IO 调用返回 EINTR。

一个例子是,异步关闭使用的 fd 时中断阻塞的线程:

https://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/solaris/native/java/net/linux_close.c

    static int closefd(int fd1, int fd2) {
...
/*
* Send a wakeup signal to all threads blocked on this
* file descriptor.
*/
threadEntry_t *curr = fdEntry->threads;
while (curr != NULL) {
curr->intr = 1;
pthread_kill( curr->thr, sigWakeup );
curr = curr->next;
}
...
}

另一个例子是中断一个套接字 channel :

https://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/sun/nio/ch/SocketChannelImpl.java

protected void implCloseSelectableChannel() throws IOException {
...
// Signal native threads, if needed. If a target thread is not
// currently blocked in an I/O operation then no harm is done since
// the signal handler doesn't actually do anything.
//
if (readerThread != 0)
NativeThread.signal(readerThread);

if (writerThread != 0)
NativeThread.signal(writerThread);
...
}

但是,可能存在被阻塞的线程将错过信号并且不会被中断的竞争。

为了演示,我写了一小段测试代码:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void handler(int sig) {
printf("singal\n");
}

int main() {
// set-up an interrupting signal handler
signal(SIGINT, handler);

// not blocking operation, prepare to block
// if the wake-up signal arrived during this
// operation. we'll miss it.
for (int i = 0; i < 2100000000; ++i) {
int j = i * i;
}
printf("not blocking operation done\n");

// blocking io operation
unsigned int remain = sleep(10);
printf("blocking io operation done, remain %u\n", remain);

return 0;
}

如果唤醒信号刚好在阻塞线程进入内核等待IO之前到达,例如执行glibc的一些包装代码,则阻塞线程将永远错过这个信号而无法被中断。

信号在 IO 之前到达时的输出如下所示:

./a.out
^Csingal
^Csingal
^Csingal
^Csingal
^Csingal
not blocking operation done
blocking io operation done, remain 0

以及信号被IO阻塞后到达时的输出:

./a.out
not blocking operation done
^Csingal
blocking io operation done, remain 6

这是 JDK 错误还是我遗漏了什么?

最佳答案

“这是 JDK 错误还是我遗漏了什么?”

您错过了重要的一点:错误是规范与实现之间的差异。 Java 规范对 linux 信号只字未提,这意味着它可以以任何方式对它们使用react,这不能被视为错误。

要证明 JDK 中存在错误,您必须在 JVM spec 中找到一个断言你认为违反了,并创建一个测试来证明 JVM 的行为与该断言规定的不同。由于 JVM 规范中的所有断言都是用字节码表示的,因此测试必须用 Java(或任何其他 JVM 语言)编写并编译为类文件。

关于java - JDK问题: interrupt another thread blocked on an IO operation with signal may fail,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53691013/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com