1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-09 21:40:33 +02:00

Protect call-with-new-thread data from GC.

* libguile/threads.c (struct launch_data): Add prev/next pointers.
  (protected_launch_data, protected_launch_data_lock): New static vars.
  (protect_launch_data, unprotect_launch_data): New functions.
  (really_launch, scm_sys_call_with_new_thread): Preserve launch data
  from GC.  Thanks to Linas Vepstas for the report!
This commit is contained in:
Andy Wingo 2017-01-11 22:17:24 +01:00
parent 7e93950552
commit 63bf6ffa0d

View file

@ -735,15 +735,49 @@ scm_call_with_new_thread (SCM thunk, SCM handler)
return scm_call_2 (call_with_new_thread, thunk, handler);
}
typedef struct {
typedef struct launch_data launch_data;
struct launch_data {
launch_data *prev;
launch_data *next;
SCM dynamic_state;
SCM thunk;
} launch_data;
};
/* GC-protect the launch data for new threads. */
static launch_data *protected_launch_data;
static scm_i_pthread_mutex_t protected_launch_data_lock =
SCM_I_PTHREAD_MUTEX_INITIALIZER;
static void
protect_launch_data (launch_data *data)
{
scm_i_pthread_mutex_lock (&protected_launch_data_lock);
data->next = protected_launch_data;
if (protected_launch_data)
protected_launch_data->prev = data;
protected_launch_data = data;
scm_i_pthread_mutex_unlock (&protected_launch_data_lock);
}
static void
unprotect_launch_data (launch_data *data)
{
scm_i_pthread_mutex_lock (&protected_launch_data_lock);
if (data->next)
data->next->prev = data->prev;
if (data->prev)
data->prev->next = data->next;
else
protected_launch_data = data->next;
scm_i_pthread_mutex_unlock (&protected_launch_data_lock);
}
static void *
really_launch (void *d)
{
scm_i_thread *t = SCM_I_CURRENT_THREAD;
unprotect_launch_data (d);
/* The thread starts with asyncs blocked. */
t->block_asyncs++;
SCM_I_CURRENT_THREAD->result = scm_call_0 (((launch_data *)d)->thunk);
@ -774,6 +808,7 @@ SCM_DEFINE (scm_sys_call_with_new_thread, "%call-with-new-thread", 1, 0, 0,
data = scm_gc_typed_calloc (launch_data);
data->dynamic_state = scm_current_dynamic_state ();
data->thunk = thunk;
protect_launch_data (data);
err = scm_i_pthread_create (&id, NULL, launch_thread, data);
if (err)
{