mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-01 01:40:21 +02:00
Don't invoke `on_thread_exit ()' from a pthread key destructor.
The `on_thread_exit ()' function allocates memory via libgc. When called from the context of a pthread key detructor, the thread is essentially "dead" already and `GC_lookup_thread ()' returns NULL, which triggers an assertion in libgc's `thread_local_alloc.c'. This patch arranges so that `on_thread_exit ()' is called from a suitable context. * libguile/threads.c (on_thread_exit): Remove now invalid comment about access to libgc's TLS. (init_thread_key): Don't pass `on_thread_exit ()' to `scm_i_pthread_key_create ()'. (scm_leave_guile_cleanup): Invoke `do_thread_exit ()'. (really_launch): Invoke `pthread_exit ()'.
This commit is contained in:
parent
979172b656
commit
47b6e9bd8e
1 changed files with 9 additions and 17 deletions
|
@ -573,22 +573,10 @@ on_thread_exit (void *v)
|
||||||
/* Unblocking the joining threads needs to happen in guile mode
|
/* Unblocking the joining threads needs to happen in guile mode
|
||||||
since the queue is a SCM data structure. */
|
since the queue is a SCM data structure. */
|
||||||
|
|
||||||
/* Note: `scm_with_guile ()' invokes `GC_local_malloc ()', which accesses
|
/* Note: Since `do_thread_exit ()' uses allocates memory via `libgc', we
|
||||||
thread-local storage (TLS). If said storage is accessed using
|
assume the GC is usable at this point, and notably that thread-local
|
||||||
`pthread_getspecific ()', then it may be inaccessible at this point,
|
storage (TLS) hasn't been deallocated yet. */
|
||||||
having been destroyed earlier, since the invocation order of destructors
|
do_thread_exit (v);
|
||||||
associated with pthread keys is unspecified:
|
|
||||||
|
|
||||||
http://www.opengroup.org/onlinepubs/009695399/functions/pthread_key_create.html
|
|
||||||
|
|
||||||
Thus, `libgc' *must* be compiled with `USE_COMPILER_TLS' for this code
|
|
||||||
to work.
|
|
||||||
|
|
||||||
FIXME: Worse, we can't use the GC at all at this point. With assertions
|
|
||||||
enabled, `libgc' triggers an assertion in `thread_local_alloc.c' upon
|
|
||||||
the next `cons' showing that `GC_lookup_thread ()' returned NULL; this
|
|
||||||
is due to the fact that we're in the thread destructor. */
|
|
||||||
scm_with_guile (do_thread_exit, v);
|
|
||||||
|
|
||||||
/* Removing ourself from the list of all threads needs to happen in
|
/* Removing ourself from the list of all threads needs to happen in
|
||||||
non-guile mode since all SCM values on our stack become
|
non-guile mode since all SCM values on our stack become
|
||||||
|
@ -619,7 +607,7 @@ static scm_i_pthread_once_t init_thread_key_once = SCM_I_PTHREAD_ONCE_INIT;
|
||||||
static void
|
static void
|
||||||
init_thread_key (void)
|
init_thread_key (void)
|
||||||
{
|
{
|
||||||
scm_i_pthread_key_create (&scm_i_thread_key, on_thread_exit);
|
scm_i_pthread_key_create (&scm_i_thread_key, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform any initializations necessary to bring the current thread
|
/* Perform any initializations necessary to bring the current thread
|
||||||
|
@ -782,6 +770,7 @@ SCM_UNUSED static void
|
||||||
scm_leave_guile_cleanup (void *x)
|
scm_leave_guile_cleanup (void *x)
|
||||||
{
|
{
|
||||||
scm_leave_guile ();
|
scm_leave_guile ();
|
||||||
|
on_thread_exit (SCM_I_CURRENT_THREAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
|
@ -890,6 +879,9 @@ really_launch (void *d)
|
||||||
else
|
else
|
||||||
t->result = scm_catch (SCM_BOOL_T, thunk, handler);
|
t->result = scm_catch (SCM_BOOL_T, thunk, handler);
|
||||||
|
|
||||||
|
/* Trigger a call to `on_thread_exit ()'. */
|
||||||
|
pthread_exit (NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue