diff options
author | Andy Wingo <wingo@pobox.com> | 2012-02-24 23:03:31 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2012-02-24 23:05:34 +0100 |
commit | 2dcf6b596526429d75f1b53ee53d64dbbfc83b53 (patch) | |
tree | 8942a2c7422be691f1596318201bdb67e015b7db | |
parent | f9c3584117d32680af91a5b2a10e262e8176bd61 (diff) | |
download | guile-2dcf6b596526429d75f1b53ee53d64dbbfc83b53.tar.gz |
fixes to threaded finalizers
* libguile/finalizers.c (finalization_thread_proc):
(run_finalization_thread):
(start_finalization_thread):
(stop_finalization_thread): Use pthreads + scm_with_guile instead of
scm_spawn_thread, to avoid deadlocks.
-rw-r--r-- | libguile/finalizers.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/libguile/finalizers.c b/libguile/finalizers.c index cabfa2c0b..07d8f0748 100644 --- a/libguile/finalizers.c +++ b/libguile/finalizers.c @@ -171,7 +171,7 @@ queue_finalizer_async (void) static int finalization_pipe[2]; static scm_i_pthread_mutex_t finalization_thread_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER; -static SCM finalization_thread = SCM_BOOL_F; +static pthread_t finalization_thread; static void notify_finalizers_to_run (void) @@ -205,7 +205,7 @@ read_finalization_pipe_data (void *data) return NULL; } -static SCM +static void* finalization_thread_proc (void *unused) { while (1) @@ -216,8 +216,8 @@ finalization_thread_proc (void *unused) if (data.n <= 0 && data.err != EINTR) { - perror ("error in finalization delivery thread"); - return SCM_UNSPECIFIED; + perror ("error in finalization thread"); + return NULL; } switch (data.byte) @@ -226,21 +226,31 @@ finalization_thread_proc (void *unused) finalization_count += GC_invoke_finalizers (); break; case 1: - return SCM_UNSPECIFIED; + return NULL; default: abort (); } } } +static void* +run_finalization_thread (void *arg) +{ + return scm_with_guile (finalization_thread_proc, arg); +} + static void start_finalization_thread (void) { scm_i_pthread_mutex_lock (&finalization_thread_lock); - if (scm_is_false (finalization_thread)) - finalization_thread = scm_spawn_thread (finalization_thread_proc, NULL, - scm_handle_by_message, - "finalization thread"); + if (!finalization_thread) + /* Use the raw pthread API and scm_with_guile, because we don't want + to block on any lock that scm_spawn_thread might want to take, + and we don't want to inherit the dynamic state (fluids) of the + caller. */ + if (pthread_create (&finalization_thread, NULL, + run_finalization_thread, NULL)) + perror ("error creating finalization thread"); scm_i_pthread_mutex_unlock (&finalization_thread_lock); } @@ -248,11 +258,12 @@ static void stop_finalization_thread (void) { scm_i_pthread_mutex_lock (&finalization_thread_lock); - if (scm_is_true (finalization_thread)) + if (finalization_thread) { notify_about_to_fork (); - scm_join_thread (finalization_thread); - finalization_thread = SCM_BOOL_F; + if (pthread_join (finalization_thread, NULL)) + perror ("joining finalization thread"); + finalization_thread = 0; } scm_i_pthread_mutex_unlock (&finalization_thread_lock); } |