@@ -19,7 +19,7 @@ use rustpython_compiler::{
1919
2020use crate :: builtins:: { self , to_ascii} ;
2121use crate :: bytecode;
22- use crate :: common:: { hash:: HashSecret , rc:: PyRc } ;
22+ use crate :: common:: { cell :: PyMutex , hash:: HashSecret , rc:: PyRc } ;
2323use crate :: exceptions:: { self , PyBaseException , PyBaseExceptionRef } ;
2424use crate :: frame:: { ExecutionResult , Frame , FrameRef } ;
2525use crate :: frozen;
@@ -122,6 +122,7 @@ pub struct PyGlobalState {
122122 pub stacksize : AtomicCell < usize > ,
123123 pub thread_count : AtomicCell < usize > ,
124124 pub hash_secret : HashSecret ,
125+ pub atexit_funcs : PyMutex < Vec < ( PyObjectRef , PyFuncArgs ) > > ,
125126}
126127
127128pub const NSIG : usize = 64 ;
@@ -258,6 +259,7 @@ impl VirtualMachine {
258259 stacksize : AtomicCell :: new ( 0 ) ,
259260 thread_count : AtomicCell :: new ( 0 ) ,
260261 hash_secret,
262+ atexit_funcs : PyMutex :: default ( ) ,
261263 } ) ,
262264 initialized : false ,
263265 } ;
@@ -344,6 +346,23 @@ impl VirtualMachine {
344346 }
345347 }
346348
349+ pub fn run_atexit_funcs ( & self ) -> PyResult < ( ) > {
350+ let mut last_exc = None ;
351+ for ( func, args) in self . state . atexit_funcs . lock ( ) . drain ( ..) . rev ( ) {
352+ if let Err ( e) = self . invoke ( & func, args) {
353+ last_exc = Some ( e. clone ( ) ) ;
354+ if !objtype:: isinstance ( & e, & self . ctx . exceptions . system_exit ) {
355+ writeln ! ( sysmodule:: PyStderr ( self ) , "Error in atexit._run_exitfuncs:" ) ;
356+ exceptions:: print_exception ( self , e) ;
357+ }
358+ }
359+ }
360+ match last_exc {
361+ None => Ok ( ( ) ) ,
362+ Some ( e) => Err ( e) ,
363+ }
364+ }
365+
347366 pub fn run_code_obj ( & self , code : PyCodeRef , scope : Scope ) -> PyResult {
348367 let frame = Frame :: new ( code, scope, self ) . into_ref ( self ) ;
349368 self . run_frame_full ( frame)
0 commit comments