diff options
author | Ludovic Courtès <ludo@gnu.org> | 2008-10-31 00:27:20 +0100 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2008-10-31 00:27:20 +0100 |
commit | 47b6e9bd8ea4c19404a990688c57f76d27f7768d (patch) | |
tree | 04ea7beb6b17669206daf37a97e87f2c79b36a12 | |
parent | 979172b6562f737232f42470a3480e99c2f0f273 (diff) | |
download | guile-47b6e9bd8ea4c19404a990688c57f76d27f7768d.tar.gz |
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 ()'.
-rw-r--r-- | libguile/threads.c | 26 |
1 files changed, 9 insertions, 17 deletions
diff --git a/libguile/threads.c b/libguile/threads.c index 5f42a8661..ac3a50290 100644 --- a/libguile/threads.c +++ b/libguile/threads.c @@ -573,22 +573,10 @@ on_thread_exit (void *v) /* Unblocking the joining threads needs to happen in guile mode since the queue is a SCM data structure. */ - /* Note: `scm_with_guile ()' invokes `GC_local_malloc ()', which accesses - thread-local storage (TLS). If said storage is accessed using - `pthread_getspecific ()', then it may be inaccessible at this point, - having been destroyed earlier, since the invocation order of destructors - 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); + /* Note: Since `do_thread_exit ()' uses allocates memory via `libgc', we + assume the GC is usable at this point, and notably that thread-local + storage (TLS) hasn't been deallocated yet. */ + do_thread_exit (v); /* Removing ourself from the list of all threads needs to happen in 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 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 @@ -782,6 +770,7 @@ SCM_UNUSED static void scm_leave_guile_cleanup (void *x) { scm_leave_guile (); + on_thread_exit (SCM_I_CURRENT_THREAD); } void * @@ -890,6 +879,9 @@ really_launch (void *d) else t->result = scm_catch (SCM_BOOL_T, thunk, handler); + /* Trigger a call to `on_thread_exit ()'. */ + pthread_exit (NULL); + return 0; } |