Skip to content

Commit 4384994

Browse files
fix: reorder impl_facade! to transition state before logging, revert do_schedule redirect
Root cause fix: co.syscall(Executing) is now called BEFORE info!("enter syscall") in both impl_facade! and WriteSyscallFacade. This triggers on_state_changed which removes MonitorListener's NOTIFY_NODE before slow logging, preventing SIGURG from firing while the coroutine is still in Running state. Reverted the do_schedule Syscall(Executing) → ready queue redirect in scheduler.rs since it's no longer needed — the MonitorListener design correctly prevents signals to Syscall-state coroutines when the NOTIFY_NODE is removed before logging. Agent-Logs-Url: https://github.com/acl-dev/open-coroutine/sessions/79faeb2b-0a58-4973-8277-f50a34bcb60b Co-authored-by: loongs-zhang <38336731+loongs-zhang@users.noreply.github.com>
1 parent ca70cd7 commit 4384994

3 files changed

Lines changed: 17 additions & 20 deletions

File tree

core/src/scheduler.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -311,17 +311,12 @@ impl<'s> Scheduler<'s> {
311311
_ = RUNNING_COROUTINES.remove(&co_id);
312312
})? {
313313
CoroutineState::Syscall((), _, state) => {
314-
if let SyscallState::Executing = state {
315-
//协程在系统调用执行期间被信号抢占,放回就绪队列以恢复执行
316-
self.ready.push(coroutine);
317-
} else {
318-
//挂起协程到系统调用表
319-
//如果已包含,说明当前系统调用还有上层父系统调用,因此直接忽略插入结果
320-
_ = self.syscall.insert(co_id, coroutine);
321-
if let SyscallState::Suspend(timestamp) = state {
322-
self.syscall_suspend
323-
.push(SyscallSuspendItem { timestamp, co_id });
324-
}
314+
//挂起协程到系统调用表
315+
//如果已包含,说明当前系统调用还有上层父系统调用,因此直接忽略插入结果
316+
_ = self.syscall.insert(co_id, coroutine);
317+
if let SyscallState::Suspend(timestamp) = state {
318+
self.syscall_suspend
319+
.push(SyscallSuspendItem { timestamp, co_id });
325320
}
326321
}
327322
CoroutineState::Suspend((), timestamp) => {

core/src/syscall/unix/mod.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,16 @@ macro_rules! impl_facade {
120120
return self.inner.$syscall(fn_ptr, $($arg, )*);
121121
}
122122
let syscall = $crate::common::constants::SyscallName::$syscall;
123-
//在日志和状态变更期间设置防重入标志,因为info!()/error!()内部会
124-
//调用write(),co.syscall()/co.running()内部会调用change_state()
125-
//再调用info!(),这些都可能触发hooked write导致无限递归
126-
// Set re-entrancy guard during logging and state changes because:
127-
// - info!()/error!() internally call write()
128-
// - co.syscall()/co.running() call change_state() which calls info!()
129-
// Both can trigger hooked write causing infinite recursion.
123+
//先转换状态再记录日志:co.syscall(Executing)会通过on_state_changed
124+
//移除MonitorListener的NOTIFY_NODE,使monitor不再发送SIGURG。
125+
//如果先调用info!()再转换状态,在QEMU等慢平台上info!()可能耗时>10ms,
126+
//导致SIGURG在协程还处于Running状态时被发送,造成抢占活锁。
127+
// Transition state BEFORE logging: co.syscall(Executing) triggers
128+
// on_state_changed which removes MonitorListener's NOTIFY_NODE,
129+
// preventing the monitor from sending SIGURG. If info!() is called
130+
// first while still in Running state, it can take >10ms on slow
131+
// platforms (QEMU), causing SIGURG to fire and preemption live-lock.
130132
$crate::syscall::set_in_facade(true);
131-
$crate::info!("enter syscall {}", syscall);
132133
if let Some(co) = $crate::scheduler::SchedulableCoroutine::current() {
133134
let new_state = $crate::common::constants::SyscallState::Executing;
134135
if co.syscall((), syscall, new_state).is_err() {
@@ -137,6 +138,7 @@ macro_rules! impl_facade {
137138
);
138139
}
139140
}
141+
$crate::info!("enter syscall {}", syscall);
140142
$crate::syscall::set_in_facade(false);
141143
let r = self.inner.$syscall(fn_ptr, $($arg, )*);
142144
$crate::syscall::set_in_facade(true);

core/src/syscall/unix/write.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ impl<I: WriteSyscall> WriteSyscall for WriteSyscallFacade<I> {
4949
}
5050
let syscall = crate::common::constants::SyscallName::write;
5151
crate::syscall::set_in_facade(true);
52-
crate::info!("enter syscall {}", syscall);
5352
if let Some(co) = crate::scheduler::SchedulableCoroutine::current() {
5453
let new_state = crate::common::constants::SyscallState::Executing;
5554
if co.syscall((), syscall, new_state).is_err() {
@@ -58,6 +57,7 @@ impl<I: WriteSyscall> WriteSyscall for WriteSyscallFacade<I> {
5857
);
5958
}
6059
}
60+
crate::info!("enter syscall {}", syscall);
6161
crate::syscall::set_in_facade(false);
6262
let r = self.inner.write(fn_ptr, fd, buf, len);
6363
crate::syscall::set_in_facade(true);

0 commit comments

Comments
 (0)