From 8f47ced2c7df646e19e401afba0236ed3482c2ca Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" <69878+youknowone@users.noreply.github.com> Date: Tue, 13 Oct 2026 14:12:22 +0900 Subject: [PATCH] Stabilize Windows all-thread traceback reads with stop-the-world (#9092) Use the existing normal dump_traceback stop-the-world path on Windows before traversing raw interpreter frames. Preserve registry-lock release before resuming threads. Signal and watchdog paths are unchanged. Assisted-by: OpenAI Codex:model identifier unavailable Co-authored-by: dot --- crates/stdlib/src/faulthandler.rs | 47 ++----------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/crates/stdlib/src/faulthandler.rs b/crates/stdlib/src/faulthandler.rs index 267326933..8e4572088 100644 --- a/crates/stdlib/src/faulthandler.rs +++ b/crates/stdlib/src/faulthandler.rs @@ -252,10 +252,10 @@ mod decl { #[cfg(any(unix, windows))] fn dump_all_threads(fd: i32, vm: &VirtualMachine) { // Get all threads' frame stacks from the shared registry - // unix: stop-the-world so every other thread is parked at a safepoint + // Stop the world so every other thread is parked at a safepoint // and its frame chain is quiescent and alive while we walk it (matches // faulthandler.dump_traceback running with the GIL held). - #[cfg(all(unix, feature = "threading"))] + #[cfg(feature = "threading")] { use core::sync::atomic::Ordering; let current_tid = rustpython_vm::stdlib::_thread::get_ident(); @@ -302,49 +302,6 @@ mod decl { dump_live_frames(fd); } - #[cfg(all(not(unix), feature = "threading"))] - { - let current_tid = rustpython_vm::stdlib::_thread::get_ident(); - let registry = vm.state.thread_frames.lock(); - - // Dump non-current threads using top_iframe, which includes - // both FrameObject and stack-allocated frames. - #[expect( - clippy::iter_over_hash_type, - reason = "Iteration order doesn't matter here" - )] - for (&tid, slot) in registry.iter() { - if tid == current_tid { - continue; - } - - let iframe_ptr = slot.top_iframe.load(core::sync::atomic::Ordering::Relaxed) - as *const rustpython_vm::frame::InterpreterFrame; - write_thread_id(fd, tid, false); - if iframe_ptr.is_null() { - puts(fd, " \n"); - } else { - let mut cur = iframe_ptr; - let mut depth = 0; - while !cur.is_null() && depth < 100 { - let iframe = unsafe { &*cur }; - dump_iframe(fd, iframe); - depth += 1; - cur = iframe.previous(); - } - if depth >= 100 && !cur.is_null() { - puts(fd, " ...\n"); - } - } - puts(fd, "\n"); - } - - // Now dump current thread from its live frame chain - // (includes stack-allocated iframes without FrameObject). - write_thread_id(fd, current_tid, true); - dump_live_frames(fd); - } - #[cfg(not(feature = "threading"))] { let _ = vm;