Here's my proposed patch to fix these problems. What do you think? Mark
>From dadcb1512569c1be039fc75f0a2967e370939e42 Mon Sep 17 00:00:00 2001 From: Mark H Weaver <m...@netris.org> Date: Thu, 28 Feb 2013 17:56:58 -0500 Subject: [PATCH] Fix thread-unsafe lazy initializations. * libguile/debug.c (scm_local_eval): libguile/ports.c (scm_current_warning_port): libguile/strports.c (scm_eval_string_in_module): Perform lazy-initialization while holding a mutex. Use SCM_UNDEFINED as the uninitialized value. Use 'scm_c_*_variable'. * doc/ref/api-modules.texi (Accessing Modules from C): Fix 'my_eval_string' example to be thread-safe. --- doc/ref/api-modules.texi | 13 +++++++------ libguile/debug.c | 8 ++++++-- libguile/ports.c | 12 ++++++++---- libguile/strports.c | 9 ++++++--- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/doc/ref/api-modules.texi b/doc/ref/api-modules.texi index 17ab462..3d111c4 100644 --- a/doc/ref/api-modules.texi +++ b/doc/ref/api-modules.texi @@ -942,14 +942,15 @@ the @var{name} is not bound in the module, signals an error. Returns a variable, always. @example -SCM my_eval_string (SCM str) -@{ - static SCM eval_string_var = SCM_BOOL_F; +static SCM eval_string_var; - if (scm_is_false (eval_string_var)) - eval_string_var = - scm_c_public_lookup ("ice-9 eval-string", "eval-string"); +void my_init (void) +@{ + eval_string_var = scm_c_public_lookup ("ice-9 eval-string", "eval-string"); +@} +SCM my_eval_string (SCM str) +@{ return scm_call_1 (scm_variable_ref (eval_string_var), str); @} @end example diff --git a/libguile/debug.c b/libguile/debug.c index b1a90d8..9e6328b 100644 --- a/libguile/debug.c +++ b/libguile/debug.c @@ -211,10 +211,14 @@ SCM_DEFINE (scm_debug_hang, "debug-hang", 0, 1, 0, SCM scm_local_eval (SCM exp, SCM env) { - static SCM local_eval_var = SCM_BOOL_F; + static SCM local_eval_var = SCM_UNDEFINED; + static scm_i_pthread_mutex_t local_eval_var_mutex + = SCM_I_PTHREAD_MUTEX_INITIALIZER; - if (scm_is_false (local_eval_var)) + scm_i_scm_pthread_mutex_lock (&local_eval_var_mutex); + if (SCM_UNBNDP (local_eval_var)) local_eval_var = scm_c_public_variable ("ice-9 local-eval", "local-eval"); + scm_i_pthread_mutex_unlock (&local_eval_var_mutex); return scm_call_2 (SCM_VARIABLE_REF (local_eval_var), exp, env); } diff --git a/libguile/ports.c b/libguile/ports.c index 55808e2..8737a76 100644 --- a/libguile/ports.c +++ b/libguile/ports.c @@ -418,10 +418,14 @@ SCM_DEFINE (scm_current_error_port, "current-error-port", 0, 0, 0, SCM scm_current_warning_port (void) { - static SCM cwp_var = SCM_BOOL_F; - - if (scm_is_false (cwp_var)) - cwp_var = scm_c_private_lookup ("guile", "current-warning-port"); + static SCM cwp_var = SCM_UNDEFINED; + static scm_i_pthread_mutex_t cwp_var_mutex + = SCM_I_PTHREAD_MUTEX_INITIALIZER; + + scm_i_scm_pthread_mutex_lock (&cwp_var_mutex); + if (SCM_UNBNDP (cwp_var)) + cwp_var = scm_c_private_variable ("guile", "current-warning-port"); + scm_i_pthread_mutex_unlock (&cwp_var_mutex); return scm_call_0 (scm_variable_ref (cwp_var)); } diff --git a/libguile/strports.c b/libguile/strports.c index 14cc93f..d1b293c 100644 --- a/libguile/strports.c +++ b/libguile/strports.c @@ -534,13 +534,16 @@ SCM_DEFINE (scm_eval_string_in_module, "eval-string", 1, 1, 0, "procedure returns.") #define FUNC_NAME s_scm_eval_string_in_module { - static SCM eval_string = SCM_BOOL_F, k_module = SCM_BOOL_F; + static SCM eval_string = SCM_UNDEFINED, k_module = SCM_UNDEFINED; + static scm_i_pthread_mutex_t init_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER; - if (scm_is_false (eval_string)) + scm_i_scm_pthread_mutex_lock (&init_mutex); + if (SCM_UNBNDP (eval_string)) { - eval_string = scm_c_public_lookup ("ice-9 eval-string", "eval-string"); + eval_string = scm_c_public_variable ("ice-9 eval-string", "eval-string"); k_module = scm_from_locale_keyword ("module"); } + scm_i_pthread_mutex_unlock (&init_mutex); if (SCM_UNBNDP (module)) module = scm_current_module (); -- 1.7.10.4