rustpython_vm/stdlib/
atexit.rs1pub use atexit::_run_exitfuncs;
2pub(crate) use atexit::module_def;
3
4#[pymodule]
5mod atexit {
6 use crate::{AsObject, PyObjectRef, PyResult, VirtualMachine, function::FuncArgs};
7
8 #[pyfunction]
9 fn register(func: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyObjectRef {
10 vm.state
12 .atexit_funcs
13 .lock()
14 .insert(0, Box::new((func.clone(), args)));
15 func
16 }
17
18 #[pyfunction]
19 fn _clear(vm: &VirtualMachine) {
20 vm.state.atexit_funcs.lock().clear();
21 }
22
23 #[pyfunction]
24 fn unregister(func: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
25 let mut i = {
28 let funcs = vm.state.atexit_funcs.lock();
29 funcs.len() as isize - 1
30 };
31 while i >= 0 {
32 let (cb, entry_ptr) = {
33 let funcs = vm.state.atexit_funcs.lock();
34 if i as usize >= funcs.len() {
35 i = funcs.len() as isize;
36 i -= 1;
37 continue;
38 }
39 let entry = &funcs[i as usize];
40 (entry.0.clone(), &**entry as *const (PyObjectRef, FuncArgs))
41 };
42 let eq = vm.bool_eq(&func, &cb)?;
44 if eq {
45 let mut funcs = vm.state.atexit_funcs.lock();
47 let mut j = (funcs.len() as isize - 1).min(i);
48 while j >= 0 {
49 if core::ptr::eq(&**funcs.get(j as usize).unwrap(), entry_ptr) {
50 funcs.remove(j as usize);
51 i = j;
52 break;
53 }
54 j -= 1;
55 }
56 }
57 {
58 let funcs = vm.state.atexit_funcs.lock();
59 if i as usize >= funcs.len() {
60 i = funcs.len() as isize;
61 }
62 }
63 i -= 1;
64 }
65 Ok(())
66 }
67
68 #[pyfunction]
69 pub fn _run_exitfuncs(vm: &VirtualMachine) {
70 let funcs: Vec<_> = core::mem::take(&mut *vm.state.atexit_funcs.lock());
71 for entry in funcs.into_iter() {
73 let (func, args) = *entry;
74 if let Err(e) = func.call(args, vm) {
75 let exit = e.fast_isinstance(vm.ctx.exceptions.system_exit);
76 let msg = func
77 .repr(vm)
78 .ok()
79 .map(|r| format!("Exception ignored in atexit callback {}", r.as_wtf8()));
80 vm.run_unraisable(e, msg, vm.ctx.none());
81 if exit {
82 break;
83 }
84 }
85 }
86 }
87
88 #[pyfunction]
89 fn _ncallbacks(vm: &VirtualMachine) -> usize {
90 vm.state.atexit_funcs.lock().len()
91 }
92}