aboutsummaryrefslogtreecommitdiff
path: root/py/modthread.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2016-05-04 09:51:01 +0000
committerDamien George <damien.p.george@gmail.com>2016-06-28 11:28:49 +0100
commit722cff5fd0debb250af827fd556dc0cab94e07d7 (patch)
tree26cb98719460705f9236c5ee7c971a177971f554 /py/modthread.c
parentf1b6db221875f6ad30ff0723f2c2302aeab70d0e (diff)
py/modthread: Be more careful with root pointers when creating a thread.
Diffstat (limited to 'py/modthread.c')
-rw-r--r--py/modthread.c36
1 files changed, 25 insertions, 11 deletions
diff --git a/py/modthread.c b/py/modthread.c
index a30be688e..4e654dfe8 100644
--- a/py/modthread.c
+++ b/py/modthread.c
@@ -142,7 +142,7 @@ typedef struct _thread_entry_args_t {
mp_obj_t fun;
size_t n_args;
size_t n_kw;
- const mp_obj_t *args;
+ mp_obj_t args[];
} thread_entry_args_t;
STATIC void *thread_entry(void *args_in) {
@@ -186,35 +186,49 @@ STATIC void *thread_entry(void *args_in) {
}
STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) {
+ // This structure holds the Python function and arguments for thread entry.
+ // We copy all arguments into this structure to keep ownership of them.
+ // We must be very careful about root pointers because this pointer may
+ // disappear from our address space before the thread is created.
+ thread_entry_args_t *th_args;
+
+ // get positional arguments
mp_uint_t pos_args_len;
mp_obj_t *pos_args_items;
mp_obj_get_array(args[1], &pos_args_len, &pos_args_items);
- thread_entry_args_t *th_args = m_new_obj(thread_entry_args_t);
- th_args->fun = args[0];
+
+ // check for keyword arguments
if (n_args == 2) {
// just position arguments
- th_args->n_args = pos_args_len;
+ th_args = m_new_obj_var(thread_entry_args_t, mp_obj_t, pos_args_len);
th_args->n_kw = 0;
- th_args->args = pos_args_items;
} else {
// positional and keyword arguments
if (mp_obj_get_type(args[2]) != &mp_type_dict) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "expecting a dict for keyword args"));
}
mp_map_t *map = &((mp_obj_dict_t*)MP_OBJ_TO_PTR(args[2]))->map;
- th_args->n_args = pos_args_len;
+ th_args = m_new_obj_var(thread_entry_args_t, mp_obj_t, pos_args_len + 2 * map->used);
th_args->n_kw = map->used;
- mp_obj_t *all_args = m_new(mp_obj_t, th_args->n_args + 2 * th_args->n_kw);
- memcpy(all_args, pos_args_items, pos_args_len * sizeof(mp_obj_t));
+ // copy across the keyword arguments
for (size_t i = 0, n = pos_args_len; i < map->alloc; ++i) {
if (MP_MAP_SLOT_IS_FILLED(map, i)) {
- all_args[n++] = map->table[i].key;
- all_args[n++] = map->table[i].value;
+ th_args->args[n++] = map->table[i].key;
+ th_args->args[n++] = map->table[i].value;
}
}
- th_args->args = all_args;
}
+
+ // copy agross the positional arguments
+ th_args->n_args = pos_args_len;
+ memcpy(th_args->args, pos_args_items, pos_args_len * sizeof(mp_obj_t));
+
+ // set the function for thread entry
+ th_args->fun = args[0];
+
+ // spawn the thread!
mp_thread_create(thread_entry, th_args, thread_stack_size);
+
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_start_new_thread_obj, 2, 3, mod_thread_start_new_thread);