[glib] Fix a possible deadlock
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] Fix a possible deadlock
- Date: Tue, 3 Aug 2010 14:43:32 +0000 (UTC)
commit b2715bbc5eaa1454df879964f58e36dbed65dc77
Author: Matthias Clasen <mclasen redhat com>
Date: Tue Aug 3 10:41:21 2010 -0400
Fix a possible deadlock
the FdSource was calling g_cancellable_disconnect while holding the
main context lock, which is bad news if the ::cancelled handler is
trying to get that lock to wake up the mainloop...
Bug 586432
gio/gasynchelper.c | 8 ++++++--
gio/tests/unix-streams.c | 22 +---------------------
2 files changed, 7 insertions(+), 23 deletions(-)
---
diff --git a/gio/gasynchelper.c b/gio/gasynchelper.c
index b439703..8e2e8e6 100644
--- a/gio/gasynchelper.c
+++ b/gio/gasynchelper.c
@@ -86,9 +86,13 @@ fd_source_finalize (GSource *source)
{
FDSource *fd_source = (FDSource *)source;
+ /* we don't use g_cancellable_disconnect() here, since we are holding
+ * the main context lock here, and the ::disconnect signal handler
+ * will try to grab that, and deadlock looms.
+ */
if (fd_source->cancelled_tag)
- g_cancellable_disconnect (fd_source->cancellable,
- fd_source->cancelled_tag);
+ g_signal_handler_disconnect (fd_source->cancellable,
+ fd_source->cancelled_tag);
if (fd_source->cancellable)
g_object_unref (fd_source->cancellable);
diff --git a/gio/tests/unix-streams.c b/gio/tests/unix-streams.c
index ea34017..2d06b8e 100644
--- a/gio/tests/unix-streams.c
+++ b/gio/tests/unix-streams.c
@@ -33,16 +33,6 @@ int writer_pipe[2], reader_pipe[2];
GCancellable *writer_cancel, *reader_cancel, *main_cancel;
GMainLoop *loop;
-static gboolean
-cancel_main (gpointer data)
-{
- GCancellable *main_cancel = data;
-
- g_cancellable_cancel (main_cancel);
-
- return FALSE;
-}
-
static gpointer
writer_thread (gpointer user_data)
@@ -74,17 +64,7 @@ writer_thread (gpointer user_data)
if (g_cancellable_is_cancelled (writer_cancel))
{
- /* FIXME: directly calling g_cancellable_cancel (main_cancel) here
- * leads to sporadic deadlock, because it will try to wake up the
- * main context, for which it needs to acquire the main context lock.
- * This lock may be held by the main loop running in the main thread,
- * and it may be held while the main thread is blocking in
- * fd_source_finalize -> g_cancellable_disconnect
- * until the ::cancelled callbacks have run.
- *
- * Work around by deferring the cancellation to a timeout.
- */
- g_timeout_add (0, cancel_main, main_cancel);
+ g_cancellable_cancel (main_cancel);
g_object_unref (out);
return NULL;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]