bug#79100: segfault with thread initialization
Rob Browning <[email protected]> Tue, 02 Sep 2025 15:38:05 -0500
| Newsgroups | gmane.lisp.guile.bugs |
|---|---|
| Message-ID | <[email protected]> |
--=-=-= Content-Type: text/plain a aa <[email protected]> writes: > # Intended behaviour > According to the [documentation]( > https://www.gnu.org/software/guile/manual/html_node/Guile-Initialization-Functions.html), > you should be able to call `scm_with_guile` concurrently. It looks like this is an issue in thread.c when multiple threads are racing, before guile has been initialized, with respect to scm_i_init_thread_for_guile. All of them will have a dynamic_state value that came from default_dynamic_state, which is 0L at startup. One of them will get the scm_i_init_mutex and initialize guile, which will set the default_dynamic_state to SCM_BOOL_F via scm_init_threads. Then, when the thread that initialized guile releases scm_i_init_mutex, the other threads will proceed, pass the stale 0L to guilify_self_2, and segfault in the is_dynamic_state call in scm_set_current_dynamic_state: (gdb) where #0 0x00007ffff7ed4eb6 in is_dynamic_state (x=0x0) at .../src/guile/up/main/libguile/fluids.c:108 #1 scm_set_current_dynamic_state (state=0x0) at .../src/guile/up/main/libguile/fluids.c:624 #2 0x00007ffff7f4476d in guilify_self_2 (dynamic_state=dynamic_state@entry=0x0) at .../src/guile/up/main/libguile/threads.c:449 #3 0x00007ffff7f48b28 in scm_i_init_thread_for_guile (base=base@entry=0x7ffff7038e60, dynamic_state=dynamic_state@entry=0x0) at .../src/guile/up/main/libguile/threads.c:599 #4 0x00007ffff7f48d56 in scm_i_init_thread_for_guile (base=0x7ffff7038e60, dynamic_state=0x0) at .../src/guile/up/main/libguile/threads.c:681 #5 with_guile (base=0x7ffff7038e60, data=0x7ffff7038e90) at .../src/guile/up/main/libguile/threads.c:642 #6 0x00007ffff7c007e4 in GC_call_with_stack_base (fn=fn@entry=0x7ffff7f48cb0 <with_guile>, arg=arg@entry=0x7ffff7038e90) at ../extra/../misc.c:2178 #7 0x00007ffff7f41ce8 in scm_i_with_guile (func=<optimized out>, data=<optimized out>, dynamic_state=<optimized out>) at .../src/guile/up/main/libguile/threads.c:692 #8 scm_with_guile (func=<optimized out>, data=<optimized out>) at .../src/guile/up/main/libguile/threads.c:698 #9 0x0000555555555188 in run_with_guile () at main.c:10 #10 0x00007ffff7cebb7b in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:448 #11 0x00007ffff7d697b8 in __GI___clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78 As an aside, I'm also not sure "who" the default_dynamic_state SCM_BOOL_F value is for (via scm_init_threads). In any case, you can "fix" the problem by having the other threads notice that they now have a stale dynamic_state and retrieve a fresh one like this: --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=refresh-init-dynamc-state.diff Content-Description: refresh-init-dynamc-state.diff diff --git a/libguile/threads.c b/libguile/threads.c index 6b4510d53..442ce4c45 100644 --- a/libguile/threads.c +++ b/libguile/threads.c @@ -368,7 +368,7 @@ static scm_i_pthread_mutex_t thread_admin_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZE static scm_thread *all_threads = NULL; static int thread_count; -static SCM default_dynamic_state; +static SCM default_dynamic_state; // Either 0 or SCM_BOOL_F during init /* Perform first stage of thread initialisation, in non-guile mode. */ @@ -595,6 +595,11 @@ scm_i_init_thread_for_guile (struct GC_stack_base *base, needs_unregister = 1; #endif + // We were blocked while another thread was initializing + // guile, so we need to re-read the (now correct) state. + if (dynamic_state == 0L || scm_is_eq (dynamic_state, SCM_BOOL_F)) + dynamic_state = default_dynamic_state; + guilify_self_1 (base, needs_unregister); guilify_self_2 (dynamic_state); } --=-=-= Content-Type: text/plain which avoids the segfault, but I suspect it may not be the fix we want. -- Rob Browning rlb @defaultvalue.org and @debian.org GPG as of 2011-07-10 E6A9 DA3C C9FD 1FF8 C676 D2C4 C0F0 39E9 ED1B 597A GPG as of 2002-11-03 14DD 432F AE39 534D B592 F9A0 25C8 D377 8C7E 73A4 --=-=-=--