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