diff --git a/Lib/concurrent/interpreters/_queues.py b/Lib/concurrent/interpreters/_queues.py index 56c947f7d..5f3ee0934 100644 --- a/Lib/concurrent/interpreters/_queues.py +++ b/Lib/concurrent/interpreters/_queues.py @@ -1,6 +1,5 @@ """Cross-interpreter Queues High Level Module.""" -import pickle import queue import time import weakref @@ -225,7 +224,7 @@ class Queue: while True: try: _queues.put(self._id, obj, unboundop) - except QueueFull as exc: + except QueueFull: if timeout is not None and time.time() >= end: raise # re-raise time.sleep(_delay) @@ -260,7 +259,7 @@ class Queue: while True: try: obj, unboundop = _queues.get(self._id) - except QueueEmpty as exc: + except QueueEmpty: if timeout is not None and time.time() >= end: raise # re-raise time.sleep(_delay) @@ -279,7 +278,7 @@ class Queue: """ try: obj, unboundop = _queues.get(self._id) - except QueueEmpty as exc: + except QueueEmpty: raise # re-raise if unboundop is not None: assert obj is None, repr(obj) diff --git a/crates/stdlib/src/syslog.rs b/crates/stdlib/src/syslog.rs index 5966dced2..cb00ee080 100644 --- a/crates/stdlib/src/syslog.rs +++ b/crates/stdlib/src/syslog.rs @@ -76,6 +76,9 @@ mod syslog { #[pyfunction] fn openlog(args: OpenLogArgs, vm: &VirtualMachine) -> PyResult<()> { + if !vm.state.is_main_interpreter() { + return Err(vm.new_runtime_error("subinterpreter can't use syslog.openlog()")); + } let logoption = args.logoption; let facility = args.facility; let ident = match args.ident.clone() { @@ -116,6 +119,11 @@ mod syslog { vm.audit("syslog.syslog", || (priority, msg.clone()))?; if !host_syslog::is_open() { + if !vm.state.is_main_interpreter() { + return Err(vm.new_runtime_error( + "subinterpreter can't use syslog.syslog() until the syslog is opened by the main interpreter", + )); + } openlog( OpenLogArgs { facility: LOG_USER, @@ -132,6 +140,9 @@ mod syslog { #[pyfunction] fn closelog(vm: &VirtualMachine) -> PyResult<()> { + if !vm.state.is_main_interpreter() { + return Err(vm.new_runtime_error("subinterpreter can't use syslog.closelog()")); + } vm.audit("syslog.closelog", || ())?; host_syslog::closelog(); diff --git a/crates/vm/src/stdlib/_thread.rs b/crates/vm/src/stdlib/_thread.rs index d086c3f76..450539908 100644 --- a/crates/vm/src/stdlib/_thread.rs +++ b/crates/vm/src/stdlib/_thread.rs @@ -805,12 +805,12 @@ pub(crate) mod _thread { 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()); + let msg = func.as_ref().repr(vm).ok().map(|repr| { + let mut message = Wtf8Buf::from("Exception ignored in thread started by "); + message.push_wtf8(repr.as_wtf8()); + vm.ctx.new_str(message) + }); + vm.run_unraisable_with_message(exc, msg, vm.ctx.none()); } fn run_thread(func: ArgCallable, args: FuncArgs, vm: &VirtualMachine) { diff --git a/crates/vm/src/vm/crossinterp.rs b/crates/vm/src/vm/crossinterp.rs index 3c2697be5..07f2ff538 100644 --- a/crates/vm/src/vm/crossinterp.rs +++ b/crates/vm/src/vm/crossinterp.rs @@ -2,7 +2,7 @@ //! //! Interpreters do not share `PyObject` graphs. Shareable values are converted //! to an interpreter-neutral payload and rebuilt in the destination. -// cspell:ignore unpickler +// cspell:ignore unpickler unmarshalled #[cfg(not(feature = "threading"))] use crate::protocol::BufferDescriptor; @@ -351,17 +351,23 @@ impl SharedValue { } fn marshal_dumps(obj: &PyObject, vm: &VirtualMachine) -> PyResult> { - let dumps = vm.import("marshal", 0)?.get_attr("dumps", vm)?; - let bytes = dumps.call((obj.to_owned(),), vm)?; - let bytes = bytes - .downcast::() - .map_err(|_| vm.new_type_error("marshal.dumps() did not return bytes"))?; - Ok(bytes.as_bytes().to_vec()) + let dump = || -> PyResult> { + let dumps = vm.import("marshal", 0)?.get_attr("dumps", vm)?; + let bytes = dumps.call((obj.to_owned(),), vm)?; + let bytes = bytes + .downcast::() + .map_err(|_| vm.new_type_error("marshal.dumps() did not return bytes"))?; + Ok(bytes.as_bytes().to_vec()) + }; + dump().map_err(|cause| not_shareable_error_from(vm, "object could not be marshalled", cause)) } fn marshal_loads(data: &[u8], vm: &VirtualMachine) -> PyResult { - let loads = vm.import("marshal", 0)?.get_attr("loads", vm)?; - loads.call((vm.ctx.new_bytes(data.to_vec()),), vm) + let load = || -> PyResult { + let loads = vm.import("marshal", 0)?.get_attr("loads", vm)?; + loads.call((vm.ctx.new_bytes(data.to_vec()),), vm) + }; + load().map_err(|cause| not_shareable_error_from(vm, "object could not be unmarshalled", cause)) } /// `_memoryview_from_xid`. diff --git a/crates/vm/src/vm/mod.rs b/crates/vm/src/vm/mod.rs index c899a8c2e..143744ec6 100644 --- a/crates/vm/src/vm/mod.rs +++ b/crates/vm/src/vm/mod.rs @@ -1816,7 +1816,16 @@ impl VirtualMachine { #[cold] pub fn run_unraisable(&self, e: PyBaseExceptionRef, msg: Option, object: PyObjectRef) { - let msg = msg.map(|msg| self.ctx.new_str(msg)); + self.run_unraisable_with_message(e, msg.map(|msg| self.ctx.new_str(msg)), object); + } + + #[cold] + pub(crate) fn run_unraisable_with_message( + &self, + e: PyBaseExceptionRef, + msg: Option, + object: PyObjectRef, + ) { let write_original = || { let msg = msg.as_ref().map(|msg| msg.to_string_lossy()); self.write_unraisable_to_stderr(&e, msg.as_deref(), &object);