Fix destructor during initialization

This commit is contained in:
Noah
2020-09-15 19:13:31 -05:00
parent 18273da108
commit ab568ccafb
2 changed files with 71 additions and 46 deletions

View File

@@ -14,45 +14,57 @@ use crate::vm::{InitParameter, VirtualMachine};
#[cfg(feature = "rustpython-compiler")]
use rustpython_compiler::compile;
pub fn init_importlib(vm: &mut VirtualMachine, initialize_parameter: InitParameter) -> PyResult {
pub fn init_importlib(
vm: &mut VirtualMachine,
initialize_parameter: InitParameter,
) -> PyResult<()> {
use crate::vm::thread::enter_vm;
flame_guard!("init importlib");
let importlib = import_frozen(vm, "_frozen_importlib")?;
let impmod = import_builtin(vm, "_imp")?;
let install = vm.get_attribute(importlib.clone(), "_install")?;
vm.invoke(&install, vec![vm.sys_module.clone(), impmod])?;
let importlib = enter_vm(vm, || {
let importlib = import_frozen(vm, "_frozen_importlib")?;
let impmod = import_builtin(vm, "_imp")?;
let install = vm.get_attribute(importlib.clone(), "_install")?;
vm.invoke(&install, vec![vm.sys_module.clone(), impmod])?;
Ok(importlib)
})?;
vm.import_func = vm.get_attribute(importlib.clone(), "__import__")?;
match initialize_parameter {
InitParameter::InitializeExternal if cfg!(feature = "rustpython-compiler") => {
flame_guard!("install_external");
let install_external = vm.get_attribute(importlib, "_install_external_importers")?;
vm.invoke(&install_external, vec![])?;
// Set pyc magic number to commit hash. Should be changed when bytecode will be more stable.
let importlib_external = vm.import("_frozen_importlib_external", &[], 0)?;
let mut magic = get_git_revision().into_bytes();
magic.truncate(4);
if magic.len() != 4 {
magic = rand::thread_rng().gen::<[u8; 4]>().to_vec();
}
vm.set_attr(&importlib_external, "MAGIC_NUMBER", vm.ctx.new_bytes(magic))?;
let zipimport_res = (|| -> PyResult<()> {
let zipimport = vm.import("zipimport", &[], 0)?;
let zipimporter = vm.get_attribute(zipimport, "zipimporter")?;
let path_hooks = vm.get_attribute(vm.sys_module.clone(), "path_hooks")?;
let path_hooks = objlist::PyListRef::try_from_object(vm, path_hooks)?;
path_hooks.insert(0, zipimporter);
enter_vm(vm, || {
flame_guard!("install_external");
let install_external =
vm.get_attribute(importlib, "_install_external_importers")?;
vm.invoke(&install_external, vec![])?;
// Set pyc magic number to commit hash. Should be changed when bytecode will be more stable.
let importlib_external = vm.import("_frozen_importlib_external", &[], 0)?;
let mut magic = get_git_revision().into_bytes();
magic.truncate(4);
if magic.len() != 4 {
magic = rand::thread_rng().gen::<[u8; 4]>().to_vec();
}
vm.set_attr(&importlib_external, "MAGIC_NUMBER", vm.ctx.new_bytes(magic))?;
let zipimport_res = (|| -> PyResult<()> {
let zipimport = vm.import("zipimport", &[], 0)?;
let zipimporter = vm.get_attribute(zipimport, "zipimporter")?;
let path_hooks = vm.get_attribute(vm.sys_module.clone(), "path_hooks")?;
let path_hooks = objlist::PyListRef::try_from_object(vm, path_hooks)?;
path_hooks.insert(0, zipimporter);
Ok(())
})();
if zipimport_res.is_err() {
warn!("couldn't init zipimport")
}
Ok(())
})();
if zipimport_res.is_err() {
warn!("couldn't init zipimport")
}
})?
}
InitParameter::NoInitialize => {
panic!("Import library initialize should be InitializeInternal or InitializeExternal");
}
_ => {}
}
Ok(vm.get_none())
Ok(())
}
pub fn import_frozen(vm: &VirtualMachine, module_name: &str) -> PyResult {

View File

@@ -69,23 +69,32 @@ pub struct VirtualMachine {
}
pub(crate) mod thread {
use super::{Interpreter, PyObjectRef, VirtualMachine};
use super::{PyObjectRef, VirtualMachine};
use itertools::Itertools;
use std::cell::RefCell;
use std::ptr::NonNull;
use std::thread_local;
thread_local! {
pub(super) static VM_STACK: RefCell<Vec<NonNull<Interpreter>>> = Vec::with_capacity(1).into();
pub(super) static VM_STACK: RefCell<Vec<NonNull<VirtualMachine>>> = Vec::with_capacity(1).into();
}
pub(crate) fn with_vm<F, R>(obj: &PyObjectRef, f: F) -> R
pub fn enter_vm<R>(vm: &VirtualMachine, f: impl FnOnce() -> R) -> R {
VM_STACK.with(|vms| {
vms.borrow_mut().push(vm.into());
let ret = std::panic::catch_unwind(std::panic::AssertUnwindSafe(f));
vms.borrow_mut().pop();
ret.unwrap_or_else(|e| std::panic::resume_unwind(e))
})
}
pub fn with_vm<F, R>(obj: &PyObjectRef, f: F) -> R
where
F: Fn(&VirtualMachine) -> R,
{
let vm_owns_obj = |intp: NonNull<Interpreter>| {
let vm_owns_obj = |intp: NonNull<VirtualMachine>| {
// SAFETY: all references in VM_STACK should be valid
let vm = unsafe { &intp.as_ref().vm };
let vm = unsafe { intp.as_ref() };
crate::obj::objtype::isinstance(obj, &vm.ctx.types.object_type)
};
VM_STACK.with(|vms| {
@@ -96,12 +105,12 @@ pub(crate) mod thread {
}
Err(mut others) => others
.find(|x| vm_owns_obj(*x))
.expect("can't get a vm; none on stack"),
.unwrap_or_else(|| panic!("can't get a vm for {:?}; none on stack", obj)),
};
// SAFETY: all references in VM_STACK should be valid, and should not be changed or moved
// at least until this function returns and the stack unwinds to an Interpreter::enter call
let intp = unsafe { intp.as_ref() };
f(&intp.vm)
// at least until this function returns and the stack unwinds to an enter_vm() call
let vm = unsafe { intp.as_ref() };
f(vm)
})
}
}
@@ -225,7 +234,6 @@ impl VirtualMachine {
let profile_func = RefCell::new(ctx.none());
let trace_func = RefCell::new(ctx.none());
let signal_handlers = RefCell::new(arr![ctx.none(); 64]);
let initialize_parameter = settings.initialization_parameter;
let stdlib_inits = stdlib::get_module_inits();
let frozen = frozen::get_module_inits();
@@ -235,7 +243,7 @@ impl VirtualMachine {
None => rand::random(),
};
let mut vm = VirtualMachine {
let vm = VirtualMachine {
builtins,
sys_module: sysmod,
ctx: PyRc::new(ctx),
@@ -267,7 +275,6 @@ impl VirtualMachine {
vm.get_none(),
);
objmodule::init_module_dict(&vm, &sysmod_dict, vm.ctx.new_str("sys"), vm.get_none());
vm.initialize(initialize_parameter);
vm
}
@@ -1576,9 +1583,8 @@ pub struct Interpreter {
impl Interpreter {
pub fn new(settings: PySettings) -> Self {
Self {
vm: VirtualMachine::new(settings),
}
let init = settings.initialization_parameter;
Self::new_with_init(settings, |_| init)
}
pub fn new_with_init<F>(settings: PySettings, init: F) -> Self
@@ -1595,11 +1601,18 @@ impl Interpreter {
where
F: FnOnce(&VirtualMachine) -> R,
{
thread::VM_STACK.with(|vms| vms.borrow_mut().push(self.into()));
let ret = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(&self.vm)));
thread::VM_STACK.with(|vms| vms.borrow_mut().pop());
ret.unwrap_or_else(|e| std::panic::resume_unwind(e))
thread::enter_vm(&self.vm, || f(&self.vm))
}
pub fn run<F>(self, f: F)
where
F: FnOnce(&VirtualMachine),
{
self.enter(f);
self.shutdown();
}
pub fn shutdown(self) {}
}
impl Default for Interpreter {