diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py index 22b19ee3d..ebb193eab 100644 --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -151,7 +151,6 @@ class ThreadRunningTests(BasicThreadTest): support.gc_collect() # For PyPy or other GCs. self.assertEqual(thread._count(), orig) - @unittest.expectedFailure # TODO: RUSTPYTHON def test_unraisable_exception(self): def task(): started.release() diff --git a/crates/vm/src/stdlib/_thread.rs b/crates/vm/src/stdlib/_thread.rs index 0079f15df..91fec0a02 100644 --- a/crates/vm/src/stdlib/_thread.rs +++ b/crates/vm/src/stdlib/_thread.rs @@ -20,7 +20,10 @@ pub(crate) mod _thread { use crate::{ AsObject, Py, PyPayload, PyRef, PyResult, VirtualMachine, - builtins::{PyDictRef, PyIntRef, PyStr, PyTupleRef, PyType, PyTypeRef, PyUtf8StrRef}, + builtins::{ + PyBaseExceptionRef, PyDictRef, PyIntRef, PyStr, PyTupleRef, PyType, PyTypeRef, + PyUtf8StrRef, + }, common::wtf8::Wtf8Buf, frame::FrameRef, function::{ArgCallable, FuncArgs, KwArgs, OptionalArg, PySetterValue, TimeoutSeconds}, @@ -558,6 +561,19 @@ pub(crate) mod _thread { .map_err(|_err| vm.new_runtime_error("can't start new thread")) } + fn report_unraisable_thread_exception( + exc: PyBaseExceptionRef, + func: &ArgCallable, + vm: &VirtualMachine, + ) { + let msg = func + .as_ref() + .repr(vm) + .ok() + .map(|repr| format!("Exception ignored in thread started by {}", repr.as_wtf8())); + vm.run_unraisable(exc, msg, vm.ctx.none()); + } + fn run_thread(func: ArgCallable, args: FuncArgs, vm: &VirtualMachine) { // Increment thread count when thread actually starts executing vm.state.thread_count.fetch_add(1); @@ -572,11 +588,7 @@ pub(crate) mod _thread { if let Err(exc) = func.invoke(args, vm) && !exc.fast_isinstance(vm.ctx.exceptions.system_exit) { - vm.run_unraisable( - exc, - Some("Exception ignored in thread started by".to_owned()), - func.into(), - ); + report_unraisable_thread_exception(exc, &func, vm); } } for lock in SENTINELS.take() { @@ -1755,11 +1767,7 @@ pub(crate) mod _thread { if let Err(exc) = func.invoke((), vm) && !exc.fast_isinstance(vm.ctx.exceptions.system_exit) { - vm.run_unraisable( - exc, - Some("Exception ignored in thread started by".to_owned()), - func.into(), - ); + report_unraisable_thread_exception(exc, &func, vm); } } })) diff --git a/crates/vm/src/vm/mod.rs b/crates/vm/src/vm/mod.rs index 28eb111a9..3062ea07f 100644 --- a/crates/vm/src/vm/mod.rs +++ b/crates/vm/src/vm/mod.rs @@ -1296,18 +1296,24 @@ impl VirtualMachine { } }; - let msg_str = if let Some(msg) = msg { - format!("{msg}: ") + if self.is_none(object) { + if let Some(msg) = msg { + write_to_stderr(&format!("{msg}:\n"), &stderr, self); + } } else { - "Exception ignored in: ".to_owned() - }; - write_to_stderr(&msg_str, &stderr, self); + let msg_str = if let Some(msg) = msg { + format!("{msg}: ") + } else { + "Exception ignored in: ".to_owned() + }; + write_to_stderr(&msg_str, &stderr, self); - let repr_result = object.repr(self); - let repr_wtf8 = repr_result - .as_ref() - .map_or_else(|_| "".as_ref(), |s| s.as_wtf8()); - write_to_stderr(&format!("{repr_wtf8}\n"), &stderr, self); + let repr_result = object.repr(self); + let repr_wtf8 = repr_result + .as_ref() + .map_or_else(|_| "".as_ref(), |s| s.as_wtf8()); + write_to_stderr(&format!("{repr_wtf8}\n"), &stderr, self); + } // Write exception type and message let exc_type_name = e.class().name();