Skip to content

Commit 36ff461

Browse files
authored
Add import_ensure_initialized to import_module_level (RustPython#7076)
Wait for module initialization to complete when a module is already in sys.modules but still being initialized by another thread. Check __spec__._initializing and call _lock_unlock_module to block until the import finishes.
1 parent 6bfdfb1 commit 36ff461

1 file changed

Lines changed: 25 additions & 1 deletion

File tree

crates/vm/src/import.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,27 @@ pub fn import_source(vm: &VirtualMachine, module_name: &str, content: &str) -> P
153153
import_code_obj(vm, module_name, code, false)
154154
}
155155

156+
/// If `__spec__._initializing` is true, wait for the module to finish
157+
/// initializing by calling `_lock_unlock_module`.
158+
fn import_ensure_initialized(
159+
module: &PyObjectRef,
160+
name: &str,
161+
vm: &VirtualMachine,
162+
) -> PyResult<()> {
163+
let initializing = match vm.get_attribute_opt(module.clone(), vm.ctx.intern_str("__spec__"))? {
164+
Some(spec) => match vm.get_attribute_opt(spec, vm.ctx.intern_str("_initializing"))? {
165+
Some(v) => v.try_to_bool(vm)?,
166+
None => false,
167+
},
168+
None => false,
169+
};
170+
if initializing {
171+
let lock_unlock = vm.importlib.get_attr("_lock_unlock_module", vm)?;
172+
lock_unlock.call((vm.ctx.new_str(name),), vm)?;
173+
}
174+
Ok(())
175+
}
176+
156177
pub fn import_code_obj(
157178
vm: &VirtualMachine,
158179
module_name: &str,
@@ -405,7 +426,10 @@ pub(crate) fn import_module_level(
405426
// import_get_module + import_find_and_load
406427
let sys_modules = vm.sys_module.get_attr("modules", vm)?;
407428
let module = match sys_modules.get_item(&*abs_name, vm) {
408-
Ok(m) if !vm.is_none(&m) => m,
429+
Ok(m) if !vm.is_none(&m) => {
430+
import_ensure_initialized(&m, &abs_name, vm)?;
431+
m
432+
}
409433
_ => {
410434
let find_and_load = vm.importlib.get_attr("_find_and_load", vm)?;
411435
let abs_name_obj = vm.ctx.new_str(&*abs_name);

0 commit comments

Comments
 (0)