1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 19:50:24 +02:00

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.
This commit is contained in:
Andy Wingo 2012-02-24 23:03:31 +01:00
parent f9c3584117
commit 2dcf6b5965

View file

@ -171,7 +171,7 @@ queue_finalizer_async (void)
static int finalization_pipe[2]; static int finalization_pipe[2];
static scm_i_pthread_mutex_t finalization_thread_lock = static scm_i_pthread_mutex_t finalization_thread_lock =
SCM_I_PTHREAD_MUTEX_INITIALIZER; SCM_I_PTHREAD_MUTEX_INITIALIZER;
static SCM finalization_thread = SCM_BOOL_F; static pthread_t finalization_thread;
static void static void
notify_finalizers_to_run (void) notify_finalizers_to_run (void)
@ -205,7 +205,7 @@ read_finalization_pipe_data (void *data)
return NULL; return NULL;
} }
static SCM static void*
finalization_thread_proc (void *unused) finalization_thread_proc (void *unused)
{ {
while (1) while (1)
@ -216,8 +216,8 @@ finalization_thread_proc (void *unused)
if (data.n <= 0 && data.err != EINTR) if (data.n <= 0 && data.err != EINTR)
{ {
perror ("error in finalization delivery thread"); perror ("error in finalization thread");
return SCM_UNSPECIFIED; return NULL;
} }
switch (data.byte) switch (data.byte)
@ -226,21 +226,31 @@ finalization_thread_proc (void *unused)
finalization_count += GC_invoke_finalizers (); finalization_count += GC_invoke_finalizers ();
break; break;
case 1: case 1:
return SCM_UNSPECIFIED; return NULL;
default: default:
abort (); abort ();
} }
} }
} }
static void*
run_finalization_thread (void *arg)
{
return scm_with_guile (finalization_thread_proc, arg);
}
static void static void
start_finalization_thread (void) start_finalization_thread (void)
{ {
scm_i_pthread_mutex_lock (&finalization_thread_lock); scm_i_pthread_mutex_lock (&finalization_thread_lock);
if (scm_is_false (finalization_thread)) if (!finalization_thread)
finalization_thread = scm_spawn_thread (finalization_thread_proc, NULL, /* Use the raw pthread API and scm_with_guile, because we don't want
scm_handle_by_message, to block on any lock that scm_spawn_thread might want to take,
"finalization thread"); 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); scm_i_pthread_mutex_unlock (&finalization_thread_lock);
} }
@ -248,11 +258,12 @@ static void
stop_finalization_thread (void) stop_finalization_thread (void)
{ {
scm_i_pthread_mutex_lock (&finalization_thread_lock); scm_i_pthread_mutex_lock (&finalization_thread_lock);
if (scm_is_true (finalization_thread)) if (finalization_thread)
{ {
notify_about_to_fork (); notify_about_to_fork ();
scm_join_thread (finalization_thread); if (pthread_join (finalization_thread, NULL))
finalization_thread = SCM_BOOL_F; perror ("joining finalization thread");
finalization_thread = 0;
} }
scm_i_pthread_mutex_unlock (&finalization_thread_lock); scm_i_pthread_mutex_unlock (&finalization_thread_lock);
} }