mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-09-30 10:56:37 +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_rw_lock_writer_unlock (&source_destroy_lock);
|
||||
|
||||
/* 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
|
||||
* 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_rw_lock_writer_unlock (&source_destroy_lock);
|
||||
|
||||
/* the context is going to die now */
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
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/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/timeouts", test_timeouts);
|
||||
|
Reference in New Issue
Block a user