diff options
author | Andy Wingo <wingo@pobox.com> | 2017-02-28 13:14:02 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2017-02-28 13:14:02 +0100 |
commit | 4c3bea3dba345567c3689bf4ba68a85f6209eb17 (patch) | |
tree | ee3f9b9ef27c8e02ff971ec0e7b3b06eced72593 | |
parent | 631e9901d84ba59ffcb21de95dbb6c9215b642c7 (diff) |
Fix support for threads already known to GC
* libguile/threads.h (scm_i_thread): Add bool tracking whether the
thread needs to be unregistered from libgc.
* libguile/threads.c (guilify_self_1): Add needs_unregister arg.
(on_thread_exit): Only unregister thread if the thread needs it.
(scm_i_init_thread_for_guile): A thread needs unregistering if
GC_register_my_thread succeeded.
(scm_threads_prehistory): Don't unregister initial thread.
Fixes #19523. Thanks to Anthonin Bonnefoy for the report.
-rw-r--r-- | libguile/threads.c | 19 | ||||
-rw-r--r-- | libguile/threads.h | 3 |
2 files changed, 17 insertions, 5 deletions
diff --git a/libguile/threads.c b/libguile/threads.c index 1faa539e1..e67616c03 100644 --- a/libguile/threads.c +++ b/libguile/threads.c @@ -372,7 +372,7 @@ static SCM default_dynamic_state; /* Perform first stage of thread initialisation, in non-guile mode. */ static void -guilify_self_1 (struct GC_stack_base *base) +guilify_self_1 (struct GC_stack_base *base, int needs_unregister) { scm_i_thread t; @@ -410,6 +410,7 @@ guilify_self_1 (struct GC_stack_base *base) t.exited = 0; t.guile_mode = 0; + t.needs_unregister = needs_unregister; /* The switcheroo. */ { @@ -523,8 +524,13 @@ on_thread_exit (void *v) scm_i_vm_free_stack (vp); } +#ifdef SCM_HAVE_THREAD_STORAGE_CLASS + scm_i_current_thread = NULL; +#endif + #if SCM_USE_PTHREAD_THREADS - GC_unregister_my_thread (); + if (t->needs_unregister) + GC_unregister_my_thread (); #endif } @@ -586,6 +592,8 @@ scm_i_init_thread_for_guile (struct GC_stack_base *base, } else { + int needs_unregister = 0; + /* Guile is already initialized, but this thread enters it for the first time. Only initialize this thread. */ @@ -593,10 +601,11 @@ scm_i_init_thread_for_guile (struct GC_stack_base *base, /* Register this thread with libgc. */ #if SCM_USE_PTHREAD_THREADS - GC_register_my_thread (base); + if (GC_register_my_thread (base) == GC_SUCCESS) + needs_unregister = 1; #endif - guilify_self_1 (base); + guilify_self_1 (base, needs_unregister); guilify_self_2 (dynamic_state); } return 1; @@ -1782,7 +1791,7 @@ scm_threads_prehistory (void *base) GC_MAKE_PROC (GC_new_proc (thread_mark), 0), 0, 1); - guilify_self_1 ((struct GC_stack_base *) base); + guilify_self_1 ((struct GC_stack_base *) base, 0); } scm_t_bits scm_tc16_thread; diff --git a/libguile/threads.h b/libguile/threads.h index 645e5eb65..55c566d23 100644 --- a/libguile/threads.h +++ b/libguile/threads.h @@ -59,6 +59,9 @@ typedef struct scm_i_thread { /* Boolean indicating whether the thread is in guile mode. */ int guile_mode; + /* Boolean indicating whether to call GC_unregister_my_thread () when + this thread exits. */ + int needs_unregister; struct scm_thread_wake_data *wake; scm_i_pthread_cond_t sleep_cond; |