3434
3535#if MICROPY_PY_ATEXIT
3636
37- typedef struct _m_atexit_node_t {
38- struct _m_atexit_node_t * prev ;
39- struct _m_atexit_node_t * next ;
40- mp_obj_t fn ;
41- } m_atexit_node_t ;
42-
43- // atexit.register(function): Functions are called LIFO when soft-reset / exit is called.
4437mp_obj_t mp_atexit_register (mp_obj_t function ) {
4538 if (!mp_obj_is_callable (function )) {
4639 mp_raise_ValueError (MP_ERROR_TEXT ("function not callable" ));
4740 }
48- m_atexit_node_t * node = m_malloc (sizeof (m_atexit_node_t ));
49- if (MP_STATE_VM (atexit ) != NULL ) {
50- MP_STATE_VM (atexit )-> prev = node ;
41+ if (MP_STATE_VM (atexit ) == NULL ) {
42+ MP_STATE_VM (atexit ) = mp_obj_new_list (0 , NULL );
5143 }
52- node -> fn = function ;
53- node -> prev = NULL ;
54- node -> next = MP_STATE_VM (atexit );
55- MP_STATE_VM (atexit ) = node ;
44+ mp_obj_list_append (MP_OBJ_FROM_PTR (MP_STATE_VM (atexit )), function );
5645 // return the passed in function so this can be used as a decorator
5746 return function ;
5847}
5948static MP_DEFINE_CONST_FUN_OBJ_1 (mp_atexit_register_obj , mp_atexit_register ) ;
6049
6150#if MICROPY_PY_ATEXIT_UNREGISTER
6251mp_obj_t mp_atexit_unregister (mp_obj_t function ) {
63- m_atexit_node_t * node = MP_STATE_VM (atexit );
64- while (node != NULL ) {
65- if (mp_obj_equal (node -> fn , function )) {
66- if (node -> next != NULL ) {
67- node -> next -> prev = node -> prev ;
68- }
69- if (node -> prev != NULL ) {
70- node -> prev -> next = node -> next ;
71- } else {
72- MP_STATE_VM (atexit ) = node -> next ;
73- }
52+ nlr_buf_t nlr ;
53+ // ValueError is thrown when function is no longer in the list
54+ if (nlr_push (& nlr ) == 0 ) {
55+ while (MP_STATE_VM (atexit ) != NULL ) {
56+ mp_obj_list_remove (MP_OBJ_FROM_PTR (MP_STATE_VM (atexit )), function );
7457 }
75- node = node -> next ;
7658 }
7759 return mp_const_none ;
7860}
@@ -86,30 +68,30 @@ static const mp_rom_map_elem_t mp_module_atexit_globals_table[] = {
8668 { MP_ROM_QSTR (MP_QSTR_unregister ), MP_ROM_PTR (& mp_atexit_unregister_obj ) },
8769 #endif
8870};
89-
9071static MP_DEFINE_CONST_DICT (mp_module_atexit_globals , mp_module_atexit_globals_table ) ;
9172
9273const mp_obj_module_t mp_module_atexit = {
9374 .base = { & mp_type_module },
9475 .globals = (mp_obj_dict_t * )& mp_module_atexit_globals ,
9576};
9677
97- MP_REGISTER_ROOT_POINTER (struct _m_atexit_node_t * atexit );
78+ MP_REGISTER_ROOT_POINTER (mp_obj_list_t * atexit );
9879MP_REGISTER_MODULE (MP_QSTR_atexit , mp_module_atexit );
9980
10081int mp_atexit_execute (void ) {
10182 int exit_code = 0 ;
102- // This function is intended to be run by a port during its soft-reset / exit.
103- // walk down linked list last in / first out and execute each function.
104- // Beware, the sys.settrace function should be disabled before running sys.atexit.
105- while (MP_STATE_VM (atexit ) != NULL ) {
106- nlr_buf_t nlr ;
107- if (nlr_push (& nlr ) == 0 ) {
108- mp_call_function_0 (MP_STATE_VM (atexit )-> fn );
109- } else {
110- exit_code = pyexec_handle_uncaught_exception (nlr .ret_val );
83+ if (MP_STATE_VM (atexit ) != NULL ) {
84+ mp_obj_list_t * list = MP_STATE_VM (atexit );
85+ for (size_t i = 0 ; i < list -> len ; i ++ ) {
86+ mp_obj_t function = list -> items [i ];
87+
88+ nlr_buf_t nlr ;
89+ if (nlr_push (& nlr ) == 0 ) {
90+ mp_call_function_0 (function );
91+ } else {
92+ exit_code = pyexec_handle_uncaught_exception (nlr .ret_val );
93+ }
11194 }
112- MP_STATE_VM (atexit ) = MP_STATE_VM (atexit )-> next ;
11395 }
11496 return exit_code ;
11597}
0 commit comments