mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-25 19:52:10 +01:00
gmain: Do not dead-look if calling g_main_loop_run from a GSource
This should fail and warn but not leaving the context acquired and locked. Add tests.
This commit is contained in:
parent
f8e440335c
commit
7d5242d34e
@ -4522,10 +4522,12 @@ g_main_loop_run (GMainLoop *loop)
|
||||
g_assert (got_ownership);
|
||||
}
|
||||
|
||||
if (loop->context->in_check_or_prepare)
|
||||
if G_UNLIKELY (loop->context->in_check_or_prepare)
|
||||
{
|
||||
g_warning ("g_main_loop_run(): called recursively from within a source's "
|
||||
"check() or prepare() member, iteration not possible.");
|
||||
g_main_context_release_unlocked (loop->context);
|
||||
UNLOCK_CONTEXT (loop->context);
|
||||
g_main_loop_unref (loop);
|
||||
return;
|
||||
}
|
||||
|
@ -1169,6 +1169,75 @@ test_unref_while_pending (void)
|
||||
g_assert_cmpint (n_finalized, ==, 1);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GSource parent;
|
||||
GMainLoop *loop;
|
||||
} LoopedSource;
|
||||
|
||||
static gboolean
|
||||
prepare_loop_run (GSource *source, gint *time)
|
||||
{
|
||||
LoopedSource *looped_source = (LoopedSource*) source;
|
||||
*time = 0;
|
||||
|
||||
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||||
"*called recursively from within a source's check() "
|
||||
"or prepare() member*");
|
||||
g_main_loop_run (looped_source->loop);
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_loop_run (GSource *source)
|
||||
{
|
||||
LoopedSource *looped_source = (LoopedSource*) source;
|
||||
|
||||
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||||
"*called recursively from within a source's check() "
|
||||
"or prepare() member*");
|
||||
g_main_loop_run (looped_source->loop);
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dispatch_loop_run (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
LoopedSource *looped_source = (LoopedSource*) source;
|
||||
|
||||
g_main_loop_quit (looped_source->loop);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
test_recursive_loop_child_sources (void)
|
||||
{
|
||||
GMainLoop *loop;
|
||||
GSource *source;
|
||||
GSourceFuncs loop_run_funcs = {
|
||||
prepare_loop_run, check_loop_run, dispatch_loop_run, NULL, NULL, NULL,
|
||||
};
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
source = g_source_new (&loop_run_funcs, sizeof (LoopedSource));
|
||||
((LoopedSource*)source)->loop = loop;
|
||||
|
||||
g_source_attach (source, NULL);
|
||||
|
||||
g_main_loop_run (loop);
|
||||
g_source_unref (source);
|
||||
|
||||
g_main_loop_unref (loop);
|
||||
}
|
||||
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
|
||||
#include <glib-unix.h>
|
||||
@ -2445,6 +2514,7 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/mainloop/invoke", test_invoke);
|
||||
g_test_add_func ("/mainloop/child_sources", test_child_sources);
|
||||
g_test_add_func ("/mainloop/recursive_child_sources", test_recursive_child_sources);
|
||||
g_test_add_func ("/mainloop/recursive_loop_child_sources", test_recursive_loop_child_sources);
|
||||
g_test_add_func ("/mainloop/swapping_child_sources", test_swapping_child_sources);
|
||||
g_test_add_func ("/mainloop/blocked_child_sources", test_blocked_child_sources);
|
||||
g_test_add_func ("/mainloop/source_time", test_source_time);
|
||||
|
Loading…
x
Reference in New Issue
Block a user