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 , mp_const_none );
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_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+ if (nlr_push (& nlr ) == 0 ) {
54+ while (MP_STATE_VM (atexit ) != NULL ) {
55+ mp_obj_list_remove (MP_STATE_VM (atexit ), function );
7456 }
75- node = node -> next ;
7657 }
7758 return mp_const_none ;
7859}
@@ -86,30 +67,30 @@ static const mp_rom_map_elem_t mp_module_atexit_globals_table[] = {
8667 { MP_ROM_QSTR (MP_QSTR_unregister ), MP_ROM_PTR (& mp_atexit_unregister_obj ) },
8768 #endif
8869};
89-
9070static MP_DEFINE_CONST_DICT (mp_module_atexit_globals , mp_module_atexit_globals_table ) ;
9171
9272const mp_obj_module_t mp_module_atexit = {
9373 .base = { & mp_type_module },
9474 .globals = (mp_obj_dict_t * )& mp_module_atexit_globals ,
9575};
9676
97- MP_REGISTER_ROOT_POINTER (struct _m_atexit_node_t * atexit );
77+ MP_REGISTER_ROOT_POINTER (mp_obj_list_t * atexit );
9878MP_REGISTER_MODULE (MP_QSTR_atexit , mp_module_atexit );
9979
10080int mp_atexit_execute (void ) {
10181 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 );
82+ if (MP_STATE_VM (atexit ) != NULL ) {
83+ mp_obj_list_t * list = MP_STATE_VM (atexit );
84+ for (size_t i = 0 ; i < list -> len ; i ++ ) {
85+ mp_obj_t function = list -> items [i ];
86+
87+ nlr_buf_t nlr ;
88+ if (nlr_push (& nlr ) == 0 ) {
89+ mp_call_function_0 (function );
90+ } else {
91+ exit_code = pyexec_handle_uncaught_exception (nlr .ret_val );
92+ }
11193 }
112- MP_STATE_VM (atexit ) = MP_STATE_VM (atexit )-> next ;
11394 }
11495 return exit_code ;
11596}
0 commit comments