Fix deadlock when signalling the thread which freed a thread pool

2006-02-15  Sebastian Wilhelmi  <seppi@seppi.de>

	* glib/gthreadpool.c: Fix deadlock when signalling the thread
	which freed a thread pool (#331110, Chris Wilson).
This commit is contained in:
Sebastian Wilhelmi
2006-02-15 22:22:26 +00:00
committed by Sebastian Wilhelmi
parent f228d40dec
commit de9cc5daf1
4 changed files with 26 additions and 3 deletions

View File

@@ -1,3 +1,8 @@
2006-02-15 Sebastian Wilhelmi <seppi@seppi.de>
* glib/gthreadpool.c: Fix deadlock when signalling the thread
which freed a thread pool (#331110, Chris Wilson).
2006-01-30 David Schleef <ds@schleef.org> 2006-01-30 David Schleef <ds@schleef.org>
* glib/grand.c: Update URL * glib/grand.c: Update URL

View File

@@ -1,3 +1,8 @@
2006-02-15 Sebastian Wilhelmi <seppi@seppi.de>
* glib/gthreadpool.c: Fix deadlock when signalling the thread
which freed a thread pool (#331110, Chris Wilson).
2006-01-30 David Schleef <ds@schleef.org> 2006-01-30 David Schleef <ds@schleef.org>
* glib/grand.c: Update URL * glib/grand.c: Update URL

View File

@@ -1,3 +1,8 @@
2006-02-15 Sebastian Wilhelmi <seppi@seppi.de>
* glib/gthreadpool.c: Fix deadlock when signalling the thread
which freed a thread pool (#331110, Chris Wilson).
2006-01-30 David Schleef <ds@schleef.org> 2006-01-30 David Schleef <ds@schleef.org>
* glib/grand.c: Update URL * glib/grand.c: Update URL

View File

@@ -120,7 +120,9 @@ g_thread_pool_thread_proxy (gpointer data)
if (!g_thread_should_run (pool, len)) if (!g_thread_should_run (pool, len))
{ {
g_mutex_lock (inform_mutex);
g_cond_broadcast (inform_cond); g_cond_broadcast (inform_cond);
g_mutex_unlock (inform_mutex);
goto_global_pool = TRUE; goto_global_pool = TRUE;
} }
else if (len > 0) else if (len > 0)
@@ -531,7 +533,7 @@ g_thread_pool_free (GThreadPool *pool,
g_return_if_fail (real); g_return_if_fail (real);
g_return_if_fail (real->running); g_return_if_fail (real->running);
/* It there's no thread allowed here, there is not much sense in /* If there's no thread allowed here, there is not much sense in
* not stopping this pool immediately, when it's not empty */ * not stopping this pool immediately, when it's not empty */
g_return_if_fail (immediate || real->max_threads != 0 || g_return_if_fail (immediate || real->max_threads != 0 ||
g_async_queue_length (real->queue) == 0); g_async_queue_length (real->queue) == 0);
@@ -544,15 +546,21 @@ g_thread_pool_free (GThreadPool *pool,
if (wait) if (wait)
{ {
g_mutex_lock (inform_mutex);
while (g_async_queue_length_unlocked (real->queue) != -real->num_threads && while (g_async_queue_length_unlocked (real->queue) != -real->num_threads &&
!(immediate && real->num_threads == 0)) !(immediate && real->num_threads == 0))
{ {
/* This locking is a bit delicate to avoid the broadcast of
* inform_cond to overtake the wait for it. Therefore the
* inform_mutex is locked before the queue is unlocked. To
* avoid deadlocks however, the queue _must_ always be
* locked before locking the inform_mutex, if both are to be
* locked at the same time. */
g_mutex_lock (inform_mutex);
g_async_queue_unlock (real->queue); g_async_queue_unlock (real->queue);
g_cond_wait (inform_cond, inform_mutex); g_cond_wait (inform_cond, inform_mutex);
g_mutex_unlock (inform_mutex);
g_async_queue_lock (real->queue); g_async_queue_lock (real->queue);
} }
g_mutex_unlock (inform_mutex);
} }
if (immediate || if (immediate ||