From 097c9b17985efe03bf7d5a1b073d81f526218c87 Mon Sep 17 00:00:00 2001 From: Tim Janik Date: Mon, 21 Dec 1998 21:43:00 +0000 Subject: there was a reference count race for hooks during invocation loops. since Mon Dec 21 21:48:29 1998 Tim Janik * glib.h: * gmain.c: there was a reference count race for hooks during invocation loops. since all (known) hook loop implementations, do currently start out with g_hook_first_valid() and iterate with g_hook_next_valid(), g_hook_first_valid() will now return a referenced hook, and g_hook_next_valid() will "eat" that, and eventually transfer it to the next hook. unfortunately this requires g_hook_next_valid() to take the hook_list as additional argument. * gmain.c (g_main_iterate): adjusted callers of g_hook_next_valid(). --- ghook.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'ghook.c') diff --git a/ghook.c b/ghook.c index b683b7c31..8705e63b9 100644 --- a/ghook.c +++ b/ghook.c @@ -286,7 +286,7 @@ g_hook_list_invoke (GHookList *hook_list, if (!was_in_call) hook->flags &= ~G_HOOK_FLAG_IN_CALL; - tmp = g_hook_next_valid (hook, may_recurse); + tmp = g_hook_next_valid (hook_list, hook, may_recurse); g_hook_unref (hook_list, hook); hook = tmp; @@ -321,7 +321,7 @@ g_hook_list_invoke_check (GHookList *hook_list, if (need_destroy) g_hook_destroy_link (hook_list, hook); - tmp = g_hook_next_valid (hook, may_recurse); + tmp = g_hook_next_valid (hook_list, hook, may_recurse); g_hook_unref (hook_list, hook); hook = tmp; @@ -357,7 +357,7 @@ g_hook_list_marshal_check (GHookList *hook_list, if (need_destroy) g_hook_destroy_link (hook_list, hook); - tmp = g_hook_next_valid (hook, may_recurse); + tmp = g_hook_next_valid (hook_list, hook, may_recurse); g_hook_unref (hook_list, hook); hook = tmp; @@ -390,7 +390,7 @@ g_hook_list_marshal (GHookList *hook_list, if (!was_in_call) hook->flags &= ~G_HOOK_FLAG_IN_CALL; - tmp = g_hook_next_valid (hook, may_recurse); + tmp = g_hook_next_valid (hook_list, hook, may_recurse); g_hook_unref (hook_list, hook); hook = tmp; @@ -408,12 +408,13 @@ g_hook_first_valid (GHookList *hook_list, GHook *hook; hook = hook_list->hooks; + g_hook_ref (hook_list, hook); if (hook) { if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook))) return hook; else - return g_hook_next_valid (hook, may_be_in_call); + return g_hook_next_valid (hook_list, hook, may_be_in_call); } } @@ -421,9 +422,14 @@ g_hook_first_valid (GHookList *hook_list, } GHook* -g_hook_next_valid (GHook *hook, - gboolean may_be_in_call) +g_hook_next_valid (GHookList *hook_list, + GHook *hook, + gboolean may_be_in_call) { + GHook *ohook = hook; + + g_return_val_if_fail (hook_list != NULL, NULL); + if (!hook) return NULL; @@ -431,10 +437,16 @@ g_hook_next_valid (GHook *hook, while (hook) { if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook))) - return hook; + { + g_hook_ref (hook_list, hook); + g_hook_unref (hook_list, ohook); + + return hook; + } hook = hook->next; } - + g_hook_unref (hook_list, ohook); + return NULL; } -- cgit v1.2.3