mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-09-30 19:06:38 +02:00
gmain: move source destroy write unlock slightly earlier
If a source is using g_source_set_callback_indirect(), then performing GSource operations within GSourceCallbackFuncs::unref should not cause a deadlock. Fixes https://gitlab.gnome.org/GNOME/glib/-/issues/3725
This commit is contained in:
@@ -574,6 +574,8 @@ retry_decrement:
|
|||||||
}
|
}
|
||||||
g_source_iter_clear (&iter);
|
g_source_iter_clear (&iter);
|
||||||
|
|
||||||
|
g_rw_lock_writer_unlock (&source_destroy_lock);
|
||||||
|
|
||||||
/* Next destroy all sources. As we still hold a reference to all of them,
|
/* Next destroy all sources. As we still hold a reference to all of them,
|
||||||
* this won't cause any of them to be freed yet and especially prevents any
|
* this won't cause any of them to be freed yet and especially prevents any
|
||||||
* source that unrefs another source from its finalize function to be freed.
|
* source that unrefs another source from its finalize function to be freed.
|
||||||
@@ -584,8 +586,6 @@ retry_decrement:
|
|||||||
g_source_destroy_internal (source, context, TRUE);
|
g_source_destroy_internal (source, context, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_rw_lock_writer_unlock (&source_destroy_lock);
|
|
||||||
|
|
||||||
/* the context is going to die now */
|
/* the context is going to die now */
|
||||||
g_return_if_fail (old_ref > 0);
|
g_return_if_fail (old_ref > 0);
|
||||||
|
|
||||||
|
@@ -2384,6 +2384,38 @@ test_maincontext_source_finalization_from_dispatch (gconstpointer user_data)
|
|||||||
g_main_context_unref (c);
|
g_main_context_unref (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
callback_source_unref (gpointer cb_data)
|
||||||
|
{
|
||||||
|
GSource *s = (GSource *) cb_data;
|
||||||
|
|
||||||
|
g_source_destroy (s);
|
||||||
|
};
|
||||||
|
|
||||||
|
static GSourceCallbackFuncs callback_funcs = {
|
||||||
|
NULL,
|
||||||
|
callback_source_unref,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_context_ref_while_in_source_callbackfuncs_unref (void)
|
||||||
|
{
|
||||||
|
GMainContext *c = g_main_context_new ();
|
||||||
|
GSource *s;
|
||||||
|
|
||||||
|
g_test_summary ("Tests if calling GSource API in GSourceCallbackFuncs.unref "
|
||||||
|
"does not deadlock attempting to retrieve the relevant GMainContext.");
|
||||||
|
g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/3725");
|
||||||
|
|
||||||
|
s = g_source_new (&source_with_source_funcs, sizeof (SourceWithSource));
|
||||||
|
g_source_set_callback_indirect (s, s, &callback_funcs);
|
||||||
|
g_source_attach (s, c);
|
||||||
|
g_source_unref (s);
|
||||||
|
|
||||||
|
g_main_context_unref (c);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
once_cb (gpointer user_data)
|
once_cb (gpointer user_data)
|
||||||
{
|
{
|
||||||
@@ -2671,6 +2703,7 @@ main (int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
g_test_add_func ("/maincontext/idle-once", test_maincontext_idle_once);
|
g_test_add_func ("/maincontext/idle-once", test_maincontext_idle_once);
|
||||||
g_test_add_func ("/maincontext/timeout-once", test_maincontext_timeout_once);
|
g_test_add_func ("/maincontext/timeout-once", test_maincontext_timeout_once);
|
||||||
|
g_test_add_func ("/maincontext/context-ref-in-source-callbackfuncs-unref", test_context_ref_while_in_source_callbackfuncs_unref);
|
||||||
|
|
||||||
g_test_add_func ("/mainloop/basic", test_mainloop_basic);
|
g_test_add_func ("/mainloop/basic", test_mainloop_basic);
|
||||||
g_test_add_func ("/mainloop/timeouts", test_timeouts);
|
g_test_add_func ("/mainloop/timeouts", test_timeouts);
|
||||||
|
Reference in New Issue
Block a user