fix(runtime): stale-PID pop retries immediately instead of taking the idle path
The phase-1 split filled Idle::next_deadline from the timers lock after the shared lock was released, which turned the stale-PID branch (formerly a 100µs poll) into a potential sleep-until-timer-deadline while runnable actors sat in the queue — a hard stall on exact(1). Stale pops are now PopResult::Retry and loop without sleeping. test(poison): strengthen regression coverage. The stop-storm test never fired the sentinel under a lock (its actors only allocate at lock-free points). Add self_stop_during_spawn_does_not_poison_shared_mutex: a stop-flagged actor whose next allocation is the Box::new(closure) inside spawn's with_shared. Validated both ways: passes with the gate, SIGABRTs (unwind-in-allocator) with the gate removed. Also alloc_interval(1) so every allocation is an observation point.
This commit is contained in:
+8
-7
@@ -797,6 +797,11 @@ fn schedule_loop(inner: &Arc<RuntimeInner>, slot: usize) {
|
||||
// ----------------------------------------------------------------
|
||||
enum PopResult {
|
||||
Work(Pid, usize, *const AtomicBool, Option<Closure>),
|
||||
/// Popped a stale PID (actor already finalized). Loop again
|
||||
/// immediately — the queue may hold runnable work right behind it,
|
||||
/// so this must NOT take the idle path (which can sleep on a timer
|
||||
/// deadline or the wake fd).
|
||||
Retry,
|
||||
Idle {
|
||||
next_deadline: Option<std::time::Instant>,
|
||||
io_outstanding: u32,
|
||||
@@ -840,13 +845,8 @@ fn schedule_loop(inner: &Arc<RuntimeInner>, slot: usize) {
|
||||
PopResult::Work(pid, sp, stop, closure)
|
||||
}
|
||||
None => {
|
||||
// Stale PID (actor already finalized). Treat as idle
|
||||
// so the outer loop retries immediately.
|
||||
PopResult::Idle {
|
||||
next_deadline: None,
|
||||
io_outstanding: 0,
|
||||
wake_fd: None,
|
||||
}
|
||||
// Stale PID (actor already finalized): retry at once.
|
||||
PopResult::Retry
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -911,6 +911,7 @@ fn schedule_loop(inner: &Arc<RuntimeInner>, slot: usize) {
|
||||
(pid, sp, stop, closure)
|
||||
}
|
||||
PopResult::AllDone => return,
|
||||
PopResult::Retry => continue,
|
||||
PopResult::Idle { next_deadline, io_outstanding, wake_fd } => {
|
||||
// Something is still in flight. Sleep on the appropriate source
|
||||
// to avoid hammering the mutex; the loop will retry on wake.
|
||||
|
||||
Reference in New Issue
Block a user