Skip to content

Commit 3b2f5d2

Browse files
fix: restore sigurg_handler Syscall state check to match master, preventing TOCTOU race deadlock
Agent-Logs-Url: https://github.com/acl-dev/open-coroutine/sessions/e64e3187-7a57-474c-92b2-30473acb5596 Co-authored-by: loongs-zhang <38336731+loongs-zhang@users.noreply.github.com>
1 parent 61c06af commit 3b2f5d2

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

core/src/monitor.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,24 @@ impl Monitor {
7878
set.remove(Signal::SIGURG);
7979
set.thread_set_mask()
8080
.expect("Failed to remove SIGURG signal mask!");
81+
//不抢占处于Syscall状态的协程。
82+
//MonitorListener的设计理念是不对Syscall状态的协程发送信号。
83+
//但由于NOTIFY_NODE移除和monitor线程遍历之间存在竞态条件,
84+
//SIGURG可能在协程刚进入Syscall状态时到达。
85+
//如果此时抢占,协程会被放入syscall_map但无人唤醒(因为没有io_uring/epoll注册),
86+
//导致死锁。
87+
// Skip preemption for coroutines in Syscall state.
88+
// MonitorListener's design is to NOT send signals to Syscall-state
89+
// coroutines. However, a race between NOTIFY_NODE removal and the
90+
// monitor's queue iteration can cause SIGURG to arrive just after
91+
// the coroutine entered Syscall state. If preempted here, the
92+
// coroutine lands in the syscall map with no io_uring/epoll/timer
93+
// registration to wake it, causing a deadlock.
94+
if let Some(co) = SchedulableCoroutine::current() {
95+
if matches!(co.state(), CoroutineState::Syscall((), _, _)) {
96+
return;
97+
}
98+
}
8199
if let Some(suspender) = SchedulableSuspender::current() {
82100
suspender.suspend();
83101
}

0 commit comments

Comments
 (0)