Skip to content

Commit 726199b

Browse files
fix: conditionally reorder change_state to prevent both live-lock and SIGURG during logging
For transitions TO Running: log before notifying listeners. MonitorListener starts the 10ms preemption timer on Running state, so logging first ensures the timer starts after the potentially slow I/O completes, preventing the preemption live-lock on QEMU. For all other transitions: notify before logging (original order). MonitorListener removes the NOTIFY_NODE for non-Running states, so removing it first prevents SIGURG from arriving during the log I/O. Agent-Logs-Url: https://github.com/acl-dev/open-coroutine/sessions/7e58a7e2-bd00-42ef-8614-002f14778590 Co-authored-by: loongs-zhang <38336731+loongs-zhang@users.noreply.github.com>
1 parent fac1168 commit 726199b

1 file changed

Lines changed: 17 additions & 8 deletions

File tree

core/src/coroutine/state.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,25 @@ where
1818
new_state: CoroutineState<Yield, Return>,
1919
) -> CoroutineState<Yield, Return> {
2020
let old_state = self.state.replace(new_state);
21-
//先打印日志再通知监听器,避免在QEMU等慢速平台上的活锁问题
22-
// Log before notifying listeners so that MonitorListener submits
23-
// the NOTIFY_NODE after the (potentially slow) log I/O completes,
24-
// preventing a preemption live-lock on slow platforms like QEMU.
25-
if let CoroutineState::Error(_) = new_state {
26-
error!("{} {:?}->{:?}", self.name(), old_state, new_state);
27-
} else {
21+
if matches!(new_state, CoroutineState::Running) {
22+
//先打印日志再通知监听器,避免在QEMU等慢速平台上的活锁问题
23+
// Log before notifying: MonitorListener starts the 10ms preemption
24+
// timer on Running state. On QEMU, info!() takes >10ms, so logging
25+
// first ensures the timer starts after the slow I/O completes.
2826
info!("{} {:?}->{:?}", self.name(), old_state, new_state);
27+
self.on_state_changed(self, old_state, new_state);
28+
} else {
29+
//先通知监听器再打印日志,确保抢占定时器在日志I/O之前被移除
30+
// Notify before logging: MonitorListener removes the NOTIFY_NODE for
31+
// non-Running states. Removing it first prevents SIGURG from arriving
32+
// during the potentially slow log I/O.
33+
self.on_state_changed(self, old_state, new_state);
34+
if let CoroutineState::Error(_) = new_state {
35+
error!("{} {:?}->{:?}", self.name(), old_state, new_state);
36+
} else {
37+
info!("{} {:?}->{:?}", self.name(), old_state, new_state);
38+
}
2939
}
30-
self.on_state_changed(self, old_state, new_state);
3140
old_state
3241
}
3342

0 commit comments

Comments
 (0)