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:
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);
}
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