@@ -142,7 +142,7 @@ typedef struct _thread_entry_args_t {
142142 mp_obj_t fun ;
143143 size_t n_args ;
144144 size_t n_kw ;
145- const mp_obj_t * args ;
145+ mp_obj_t args [] ;
146146} thread_entry_args_t ;
147147
148148STATIC void * thread_entry (void * args_in ) {
@@ -186,35 +186,49 @@ STATIC void *thread_entry(void *args_in) {
186186}
187187
188188STATIC mp_obj_t mod_thread_start_new_thread (size_t n_args , const mp_obj_t * args ) {
189+ // This structure holds the Python function and arguments for thread entry.
190+ // We copy all arguments into this structure to keep ownership of them.
191+ // We must be very careful about root pointers because this pointer may
192+ // disappear from our address space before the thread is created.
193+ thread_entry_args_t * th_args ;
194+
195+ // get positional arguments
189196 mp_uint_t pos_args_len ;
190197 mp_obj_t * pos_args_items ;
191198 mp_obj_get_array (args [1 ], & pos_args_len , & pos_args_items );
192- thread_entry_args_t * th_args = m_new_obj ( thread_entry_args_t );
193- th_args -> fun = args [ 0 ];
199+
200+ // check for keyword arguments
194201 if (n_args == 2 ) {
195202 // just position arguments
196- th_args -> n_args = pos_args_len ;
203+ th_args = m_new_obj_var ( thread_entry_args_t , mp_obj_t , pos_args_len ) ;
197204 th_args -> n_kw = 0 ;
198- th_args -> args = pos_args_items ;
199205 } else {
200206 // positional and keyword arguments
201207 if (mp_obj_get_type (args [2 ]) != & mp_type_dict ) {
202208 nlr_raise (mp_obj_new_exception_msg (& mp_type_TypeError , "expecting a dict for keyword args" ));
203209 }
204210 mp_map_t * map = & ((mp_obj_dict_t * )MP_OBJ_TO_PTR (args [2 ]))-> map ;
205- th_args -> n_args = pos_args_len ;
211+ th_args = m_new_obj_var ( thread_entry_args_t , mp_obj_t , pos_args_len + 2 * map -> used ) ;
206212 th_args -> n_kw = map -> used ;
207- mp_obj_t * all_args = m_new (mp_obj_t , th_args -> n_args + 2 * th_args -> n_kw );
208- memcpy (all_args , pos_args_items , pos_args_len * sizeof (mp_obj_t ));
213+ // copy across the keyword arguments
209214 for (size_t i = 0 , n = pos_args_len ; i < map -> alloc ; ++ i ) {
210215 if (MP_MAP_SLOT_IS_FILLED (map , i )) {
211- all_args [n ++ ] = map -> table [i ].key ;
212- all_args [n ++ ] = map -> table [i ].value ;
216+ th_args -> args [n ++ ] = map -> table [i ].key ;
217+ th_args -> args [n ++ ] = map -> table [i ].value ;
213218 }
214219 }
215- th_args -> args = all_args ;
216220 }
221+
222+ // copy agross the positional arguments
223+ th_args -> n_args = pos_args_len ;
224+ memcpy (th_args -> args , pos_args_items , pos_args_len * sizeof (mp_obj_t ));
225+
226+ // set the function for thread entry
227+ th_args -> fun = args [0 ];
228+
229+ // spawn the thread!
217230 mp_thread_create (thread_entry , th_args , thread_stack_size );
231+
218232 return mp_const_none ;
219233}
220234STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (mod_thread_start_new_thread_obj , 2 , 3 , mod_thread_start_new_thread );
0 commit comments