mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-26 04:02:09 +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);
|
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 "
|
g_warning ("g_main_loop_run(): called recursively from within a source's "
|
||||||
"check() or prepare() member, iteration not possible.");
|
"check() or prepare() member, iteration not possible.");
|
||||||
|
g_main_context_release_unlocked (loop->context);
|
||||||
|
UNLOCK_CONTEXT (loop->context);
|
||||||
g_main_loop_unref (loop);
|
g_main_loop_unref (loop);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1169,6 +1169,75 @@ test_unref_while_pending (void)
|
|||||||
g_assert_cmpint (n_finalized, ==, 1);
|
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
|
#ifdef G_OS_UNIX
|
||||||
|
|
||||||
#include <glib-unix.h>
|
#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/invoke", test_invoke);
|
||||||
g_test_add_func ("/mainloop/child_sources", test_child_sources);
|
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_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/swapping_child_sources", test_swapping_child_sources);
|
||||||
g_test_add_func ("/mainloop/blocked_child_sources", test_blocked_child_sources);
|
g_test_add_func ("/mainloop/blocked_child_sources", test_blocked_child_sources);
|
||||||
g_test_add_func ("/mainloop/source_time", test_source_time);
|
g_test_add_func ("/mainloop/source_time", test_source_time);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user