diff options
Diffstat (limited to 'gobject/gsignal.c')
-rw-r--r-- | gobject/gsignal.c | 352 |
1 files changed, 215 insertions, 137 deletions
diff --git a/gobject/gsignal.c b/gobject/gsignal.c index fb85fd6ba..4bd918406 100644 --- a/gobject/gsignal.c +++ b/gobject/gsignal.c @@ -1,6 +1,8 @@ /* GObject - GLib Type, Object, Parameter and Signal Library * Copyright (C) 2000-2001 Red Hat, Inc. * + * SPDX-License-Identifier: LGPL-2.1-or-later + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -953,9 +955,9 @@ _g_signals_destroy (GType itype) if (node->itype == itype) { if (node->destroyed) - g_warning (G_STRLOC ": signal \"%s\" of type '%s' already destroyed", - node->name, - type_debug_name (node->itype)); + g_critical (G_STRLOC ": signal \"%s\" of type '%s' already destroyed", + node->name, + type_debug_name (node->itype)); else signal_destroy_R (node); } @@ -991,7 +993,7 @@ g_signal_stop_emission (gpointer instance, node = LOOKUP_SIGNAL_NODE (signal_id); if (node && detail && !(node->flags & G_SIGNAL_DETAILED)) { - g_warning ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail); + g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail); SIGNAL_UNLOCK (); return; } @@ -1002,17 +1004,17 @@ g_signal_stop_emission (gpointer instance, if (emission) { if (emission->state == EMISSION_HOOK) - g_warning (G_STRLOC ": emission of signal \"%s\" for instance '%p' cannot be stopped from emission hook", - node->name, instance); + g_critical (G_STRLOC ": emission of signal \"%s\" for instance '%p' cannot be stopped from emission hook", + node->name, instance); else if (emission->state == EMISSION_RUN) emission->state = EMISSION_STOP; } else - g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance '%p'", - node->name, instance); + g_critical (G_STRLOC ": no emission of signal \"%s\" to stop for instance '%p'", + node->name, instance); } else - g_warning ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance); + g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance); SIGNAL_UNLOCK (); } @@ -1064,19 +1066,19 @@ g_signal_add_emission_hook (guint signal_id, node = LOOKUP_SIGNAL_NODE (signal_id); if (!node || node->destroyed) { - g_warning ("%s: invalid signal id '%u'", G_STRLOC, signal_id); + g_critical ("%s: invalid signal id '%u'", G_STRLOC, signal_id); SIGNAL_UNLOCK (); return 0; } if (node->flags & G_SIGNAL_NO_HOOKS) { - g_warning ("%s: signal id '%u' does not support emission hooks (G_SIGNAL_NO_HOOKS flag set)", G_STRLOC, signal_id); + g_critical ("%s: signal id '%u' does not support emission hooks (G_SIGNAL_NO_HOOKS flag set)", G_STRLOC, signal_id); SIGNAL_UNLOCK (); return 0; } if (detail && !(node->flags & G_SIGNAL_DETAILED)) { - g_warning ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail); + g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail); SIGNAL_UNLOCK (); return 0; } @@ -1126,11 +1128,11 @@ g_signal_remove_emission_hook (guint signal_id, node = LOOKUP_SIGNAL_NODE (signal_id); if (!node || node->destroyed) { - g_warning ("%s: invalid signal id '%u'", G_STRLOC, signal_id); + g_critical ("%s: invalid signal id '%u'", G_STRLOC, signal_id); goto out; } else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_id)) - g_warning ("%s: signal \"%s\" had no hook (%lu) to remove", G_STRLOC, node->name, hook_id); + g_critical ("%s: signal \"%s\" had no hook (%lu) to remove", G_STRLOC, node->name, hook_id); node->single_va_closure_is_valid = FALSE; @@ -1214,12 +1216,17 @@ g_signal_parse_name (const gchar *detailed_signal, SIGNAL_LOCK (); signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark); - SIGNAL_UNLOCK (); node = signal_id ? LOOKUP_SIGNAL_NODE (signal_id) : NULL; + if (!node || node->destroyed || (detail && !(node->flags & G_SIGNAL_DETAILED))) - return FALSE; + { + SIGNAL_UNLOCK (); + return FALSE; + } + + SIGNAL_UNLOCK (); if (signal_id_p) *signal_id_p = signal_id; @@ -1258,10 +1265,10 @@ g_signal_stop_emission_by_name (gpointer instance, SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); if (detail && !(node->flags & G_SIGNAL_DETAILED)) - g_warning ("%s: signal '%s' does not support details", G_STRLOC, detailed_signal); + g_critical ("%s: signal '%s' does not support details", G_STRLOC, detailed_signal); else if (!g_type_is_a (itype, node->itype)) - g_warning ("%s: signal '%s' is invalid for instance '%p' of type '%s'", - G_STRLOC, detailed_signal, instance, g_type_name (itype)); + g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'", + G_STRLOC, detailed_signal, instance, g_type_name (itype)); else { Emission *emission = emission_find (signal_id, detail, instance); @@ -1269,19 +1276,19 @@ g_signal_stop_emission_by_name (gpointer instance, if (emission) { if (emission->state == EMISSION_HOOK) - g_warning (G_STRLOC ": emission of signal \"%s\" for instance '%p' cannot be stopped from emission hook", - node->name, instance); + g_critical (G_STRLOC ": emission of signal \"%s\" for instance '%p' cannot be stopped from emission hook", + node->name, instance); else if (emission->state == EMISSION_RUN) emission->state = EMISSION_STOP; } else - g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance '%p'", - node->name, instance); + g_critical (G_STRLOC ": no emission of signal \"%s\" to stop for instance '%p'", + node->name, instance); } } else - g_warning ("%s: signal '%s' is invalid for instance '%p' of type '%s'", - G_STRLOC, detailed_signal, instance, g_type_name (itype)); + g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'", + G_STRLOC, detailed_signal, instance, g_type_name (itype)); SIGNAL_UNLOCK (); } @@ -1319,11 +1326,11 @@ g_signal_lookup (const gchar *name, { /* give elaborate warnings */ if (!g_type_name (itype)) - g_warning (G_STRLOC ": unable to look up signal \"%s\" for invalid type id '%"G_GSIZE_FORMAT"'", - name, itype); + g_critical (G_STRLOC ": unable to look up signal \"%s\" for invalid type id '%"G_GSIZE_FORMAT"'", + name, itype); else if (!g_signal_is_valid_name (name)) - g_warning (G_STRLOC ": unable to look up invalid signal name \"%s\" on type '%s'", - name, g_type_name (itype)); + g_critical (G_STRLOC ": unable to look up invalid signal name \"%s\" on type '%s'", + name, g_type_name (itype)); } return signal_id; @@ -1368,14 +1375,14 @@ g_signal_list_ids (GType itype, { /* give elaborate warnings */ if (!g_type_name (itype)) - g_warning (G_STRLOC ": unable to list signals for invalid type id '%"G_GSIZE_FORMAT"'", - itype); + g_critical (G_STRLOC ": unable to list signals for invalid type id '%"G_GSIZE_FORMAT"'", + itype); else if (!G_TYPE_IS_INSTANTIATABLE (itype) && !G_TYPE_IS_INTERFACE (itype)) - g_warning (G_STRLOC ": unable to list signals of non instantiatable type '%s'", - g_type_name (itype)); + g_critical (G_STRLOC ": unable to list signals of non instantiatable type '%s'", + g_type_name (itype)); else if (!g_type_class_peek (itype) && !G_TYPE_IS_INTERFACE (itype)) - g_warning (G_STRLOC ": unable to list signals of unloaded type '%s'", - g_type_name (itype)); + g_critical (G_STRLOC ": unable to list signals of unloaded type '%s'", + g_type_name (itype)); } return (guint*) g_array_free (result, FALSE); @@ -1547,7 +1554,7 @@ g_signal_new (const gchar *signal_name, * an object definition, instead the function pointer is passed * directly and can be overridden by derived classes with * g_signal_override_class_closure() or - * g_signal_override_class_handler()and chained to with + * g_signal_override_class_handler() and chained to with * g_signal_chain_from_overridden() or * g_signal_chain_from_overridden_handler(). * @@ -1736,20 +1743,20 @@ g_signal_newv (const gchar *signal_name, node = LOOKUP_SIGNAL_NODE (signal_id); if (node && !node->destroyed) { - g_warning (G_STRLOC ": signal \"%s\" already exists in the '%s' %s", - name, - type_debug_name (node->itype), - G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry"); + g_critical (G_STRLOC ": signal \"%s\" already exists in the '%s' %s", + name, + type_debug_name (node->itype), + G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry"); g_free (signal_name_copy); SIGNAL_UNLOCK (); return 0; } if (node && node->itype != itype) { - g_warning (G_STRLOC ": signal \"%s\" for type '%s' was previously created for type '%s'", - name, - type_debug_name (itype), - type_debug_name (node->itype)); + g_critical (G_STRLOC ": signal \"%s\" for type '%s' was previously created for type '%s'", + name, + type_debug_name (itype), + type_debug_name (node->itype)); g_free (signal_name_copy); SIGNAL_UNLOCK (); return 0; @@ -1757,16 +1764,16 @@ g_signal_newv (const gchar *signal_name, for (i = 0; i < n_params; i++) if (!G_TYPE_IS_VALUE (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE)) { - g_warning (G_STRLOC ": parameter %d of type '%s' for signal \"%s::%s\" is not a value type", - i + 1, type_debug_name (param_types[i]), type_debug_name (itype), name); + g_critical (G_STRLOC ": parameter %d of type '%s' for signal \"%s::%s\" is not a value type", + i + 1, type_debug_name (param_types[i]), type_debug_name (itype), name); g_free (signal_name_copy); SIGNAL_UNLOCK (); return 0; } if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE)) { - g_warning (G_STRLOC ": return value of type '%s' for signal \"%s::%s\" is not a value type", - type_debug_name (return_type), type_debug_name (itype), name); + g_critical (G_STRLOC ": return value of type '%s' for signal \"%s::%s\" is not a value type", + type_debug_name (return_type), type_debug_name (itype), name); g_free (signal_name_copy); SIGNAL_UNLOCK (); return 0; @@ -2072,13 +2079,13 @@ g_signal_override_class_closure (guint signal_id, node = LOOKUP_SIGNAL_NODE (signal_id); node_check_deprecated (node); if (!g_type_is_a (instance_type, node->itype)) - g_warning ("%s: type '%s' cannot be overridden for signal id '%u'", G_STRLOC, type_debug_name (instance_type), signal_id); + g_critical ("%s: type '%s' cannot be overridden for signal id '%u'", G_STRLOC, type_debug_name (instance_type), signal_id); else { ClassClosure *cc = signal_find_class_closure (node, instance_type); if (cc && cc->instance_type == instance_type) - g_warning ("%s: type '%s' is already overridden for signal id '%u'", G_STRLOC, type_debug_name (instance_type), signal_id); + g_critical ("%s: type '%s' is already overridden for signal id '%u'", G_STRLOC, type_debug_name (instance_type), signal_id); else signal_add_class_closure (node, instance_type, class_closure); } @@ -2120,8 +2127,8 @@ g_signal_override_class_handler (const gchar *signal_name, g_signal_override_class_closure (signal_id, instance_type, g_cclosure_new (class_handler, NULL, NULL)); else - g_warning ("%s: signal name '%s' is invalid for type id '%"G_GSIZE_FORMAT"'", - G_STRLOC, signal_name, instance_type); + g_critical ("%s: signal name '%s' is invalid for type id '%"G_GSIZE_FORMAT"'", + G_STRLOC, signal_name, instance_type); } @@ -2177,10 +2184,10 @@ g_signal_chain_from_overridden (const GValue *instance_and_params, } } else - g_warning ("%s: signal id '%u' cannot be chained from current emission stage for instance '%p'", G_STRLOC, node->signal_id, instance); + g_critical ("%s: signal id '%u' cannot be chained from current emission stage for instance '%p'", G_STRLOC, node->signal_id, instance); } else - g_warning ("%s: no signal is currently being emitted for instance '%p'", G_STRLOC, instance); + g_critical ("%s: no signal is currently being emitted for instance '%p'", G_STRLOC, instance); if (closure) { @@ -2250,10 +2257,10 @@ g_signal_chain_from_overridden_handler (gpointer instance, } } else - g_warning ("%s: signal id '%u' cannot be chained from current emission stage for instance '%p'", G_STRLOC, node->signal_id, instance); + g_critical ("%s: signal id '%u' cannot be chained from current emission stage for instance '%p'", G_STRLOC, node->signal_id, instance); } else - g_warning ("%s: no signal is currently being emitted for instance '%p'", G_STRLOC, instance); + g_critical ("%s: no signal is currently being emitted for instance '%p'", G_STRLOC, instance); if (closure) { @@ -2282,7 +2289,7 @@ g_signal_chain_from_overridden_handler (gpointer instance, &error); if (error) { - g_warning ("%s: %s", G_STRLOC, error); + g_critical ("%s: %s", G_STRLOC, error); g_free (error); /* we purposely leak the value here, it might not be @@ -2338,7 +2345,7 @@ g_signal_chain_from_overridden_handler (gpointer instance, } else { - g_warning ("%s: %s", G_STRLOC, error); + g_critical ("%s: %s", G_STRLOC, error); g_free (error); /* we purposely leak the value here, it might not be @@ -2393,6 +2400,9 @@ g_signal_get_invocation_hint (gpointer instance) * * Connects a closure to a signal for a particular object. * + * If @closure is a floating reference (see g_closure_sink()), this function + * takes ownership of @closure. + * * Returns: the handler ID (always greater than 0 for successful connections) */ gulong @@ -2414,17 +2424,17 @@ g_signal_connect_closure_by_id (gpointer instance, if (node) { if (detail && !(node->flags & G_SIGNAL_DETAILED)) - g_warning ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail); + g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail); else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) - g_warning ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance); + g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance); else { Handler *handler = handler_new (signal_id, instance, after); if (G_TYPE_IS_OBJECT (node->itype)) - _g_object_set_has_signal_handler ((GObject *)instance); + _g_object_set_has_signal_handler ((GObject *) instance, signal_id); - handler_seq_no = handler->sequential_number; + handler_seq_no = handler->sequential_number; handler->detail = detail; handler->closure = g_closure_ref (closure); g_closure_sink (closure); @@ -2439,7 +2449,7 @@ g_signal_connect_closure_by_id (gpointer instance, } } else - g_warning ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance); + g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance); SIGNAL_UNLOCK (); return handler_seq_no; @@ -2455,6 +2465,9 @@ g_signal_connect_closure_by_id (gpointer instance, * * Connects a closure to a signal for a particular object. * + * If @closure is a floating reference (see g_closure_sink()), this function + * takes ownership of @closure. + * * Returns: the handler ID (always greater than 0 for successful connections) */ gulong @@ -2480,18 +2493,18 @@ g_signal_connect_closure (gpointer instance, SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); if (detail && !(node->flags & G_SIGNAL_DETAILED)) - g_warning ("%s: signal '%s' does not support details", G_STRLOC, detailed_signal); + g_critical ("%s: signal '%s' does not support details", G_STRLOC, detailed_signal); else if (!g_type_is_a (itype, node->itype)) - g_warning ("%s: signal '%s' is invalid for instance '%p' of type '%s'", - G_STRLOC, detailed_signal, instance, g_type_name (itype)); + g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'", + G_STRLOC, detailed_signal, instance, g_type_name (itype)); else { Handler *handler = handler_new (signal_id, instance, after); if (G_TYPE_IS_OBJECT (node->itype)) - _g_object_set_has_signal_handler ((GObject *)instance); + _g_object_set_has_signal_handler ((GObject *) instance, signal_id); - handler_seq_no = handler->sequential_number; + handler_seq_no = handler->sequential_number; handler->detail = detail; handler->closure = g_closure_ref (closure); g_closure_sink (closure); @@ -2506,8 +2519,8 @@ g_signal_connect_closure (gpointer instance, } } else - g_warning ("%s: signal '%s' is invalid for instance '%p' of type '%s'", - G_STRLOC, detailed_signal, instance, g_type_name (itype)); + g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'", + G_STRLOC, detailed_signal, instance, g_type_name (itype)); SIGNAL_UNLOCK (); return handler_seq_no; @@ -2584,16 +2597,16 @@ g_signal_connect_data (gpointer instance, node_check_deprecated (node); if (detail && !(node->flags & G_SIGNAL_DETAILED)) - g_warning ("%s: signal '%s' does not support details", G_STRLOC, detailed_signal); + g_critical ("%s: signal '%s' does not support details", G_STRLOC, detailed_signal); else if (!g_type_is_a (itype, node->itype)) - g_warning ("%s: signal '%s' is invalid for instance '%p' of type '%s'", - G_STRLOC, detailed_signal, instance, g_type_name (itype)); + g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'", + G_STRLOC, detailed_signal, instance, g_type_name (itype)); else { Handler *handler = handler_new (signal_id, instance, after); if (G_TYPE_IS_OBJECT (node->itype)) - _g_object_set_has_signal_handler ((GObject *)instance); + _g_object_set_has_signal_handler ((GObject *) instance, signal_id); handler_seq_no = handler->sequential_number; handler->detail = detail; @@ -2609,13 +2622,17 @@ g_signal_connect_data (gpointer instance, } } else - g_warning ("%s: signal '%s' is invalid for instance '%p' of type '%s'", - G_STRLOC, detailed_signal, instance, g_type_name (itype)); + g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'", + G_STRLOC, detailed_signal, instance, g_type_name (itype)); SIGNAL_UNLOCK (); return handler_seq_no; } +static void +signal_handler_block_unlocked (gpointer instance, + gulong handler_id); + /** * g_signal_handler_block: * @instance: (type GObject.Object): The instance to block the signal handler of. @@ -2634,12 +2651,20 @@ void g_signal_handler_block (gpointer instance, gulong handler_id) { - Handler *handler; - g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); g_return_if_fail (handler_id > 0); SIGNAL_LOCK (); + signal_handler_block_unlocked (instance, handler_id); + SIGNAL_UNLOCK (); +} + +static void +signal_handler_block_unlocked (gpointer instance, + gulong handler_id) +{ + Handler *handler; + handler = handler_lookup (instance, handler_id, NULL, NULL); if (handler) { @@ -2650,10 +2675,13 @@ g_signal_handler_block (gpointer instance, handler->block_count += 1; } else - g_warning ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id); - SIGNAL_UNLOCK (); + g_critical ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id); } +static void +signal_handler_unblock_unlocked (gpointer instance, + gulong handler_id); + /** * g_signal_handler_unblock: * @instance: (type GObject.Object): The instance to unblock the signal handler of. @@ -2677,25 +2705,36 @@ void g_signal_handler_unblock (gpointer instance, gulong handler_id) { - Handler *handler; - g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); g_return_if_fail (handler_id > 0); SIGNAL_LOCK (); + signal_handler_unblock_unlocked (instance, handler_id); + SIGNAL_UNLOCK (); +} + +static void +signal_handler_unblock_unlocked (gpointer instance, + gulong handler_id) +{ + Handler *handler; + handler = handler_lookup (instance, handler_id, NULL, NULL); if (handler) { if (handler->block_count) handler->block_count -= 1; else - g_warning (G_STRLOC ": handler '%lu' of instance '%p' is not blocked", handler_id, instance); + g_critical (G_STRLOC ": handler '%lu' of instance '%p' is not blocked", handler_id, instance); } else - g_warning ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id); - SIGNAL_UNLOCK (); + g_critical ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id); } +static void +signal_handler_disconnect_unlocked (gpointer instance, + gulong handler_id); + /** * g_signal_handler_disconnect: * @instance: (type GObject.Object): The instance to remove the signal handler from. @@ -2712,12 +2751,20 @@ void g_signal_handler_disconnect (gpointer instance, gulong handler_id) { - Handler *handler; - g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); g_return_if_fail (handler_id > 0); SIGNAL_LOCK (); + signal_handler_disconnect_unlocked (instance, handler_id); + SIGNAL_UNLOCK (); +} + +static void +signal_handler_disconnect_unlocked (gpointer instance, + gulong handler_id) +{ + Handler *handler; + handler = handler_lookup (instance, handler_id, 0, 0); if (handler) { @@ -2728,8 +2775,7 @@ g_signal_handler_disconnect (gpointer instance, handler_unref_R (handler->signal_id, instance, handler); } else - g_warning ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id); - SIGNAL_UNLOCK (); + g_critical ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id); } /** @@ -2860,33 +2906,31 @@ g_signal_handler_find (gpointer instance, return handler_seq_no; } +typedef void (*CallbackHandlerFunc) (gpointer instance, gulong handler_seq_no); + static guint -signal_handlers_foreach_matched_R (gpointer instance, - GSignalMatchType mask, - guint signal_id, - GQuark detail, - GClosure *closure, - gpointer func, - gpointer data, - void (*callback) (gpointer instance, - gulong handler_seq_no)) +signal_handlers_foreach_matched_unlocked_R (gpointer instance, + GSignalMatchType mask, + guint signal_id, + GQuark detail, + GClosure *closure, + gpointer func, + gpointer data, + CallbackHandlerFunc callback) { HandlerMatch *mlist; guint n_handlers = 0; - + mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE); while (mlist) { n_handlers++; if (mlist->handler->sequential_number) - { - SIGNAL_UNLOCK (); - callback (instance, mlist->handler->sequential_number); - SIGNAL_LOCK (); - } + callback (instance, mlist->handler->sequential_number); + mlist = handler_match_free1_R (mlist, instance); } - + return n_handlers; } @@ -2902,13 +2946,19 @@ signal_handlers_foreach_matched_R (gpointer instance, * @data: (nullable) (closure closure): The closure data of the handlers' closures. * * Blocks all handlers on an instance that match a certain selection criteria. - * The criteria mask is passed as an OR-ed combination of #GSignalMatchType - * flags, and the criteria values are passed as arguments. - * Passing at least one of the %G_SIGNAL_MATCH_CLOSURE, %G_SIGNAL_MATCH_FUNC + * + * The criteria mask is passed as a combination of #GSignalMatchType flags, and + * the criteria values are passed as arguments. A handler must match on all + * flags set in @mask to be blocked (i.e. the match is conjunctive). + * + * Passing at least one of the %G_SIGNAL_MATCH_ID, %G_SIGNAL_MATCH_CLOSURE, + * %G_SIGNAL_MATCH_FUNC * or %G_SIGNAL_MATCH_DATA match flags is required for successful matches. * If no handlers were found, 0 is returned, the number of blocked handlers * otherwise. * + * Support for %G_SIGNAL_MATCH_ID was added in GLib 2.78. + * * Returns: The number of handlers that matched. */ guint @@ -2925,12 +2975,13 @@ g_signal_handlers_block_matched (gpointer instance, g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); - if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) + if (mask & (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) { SIGNAL_LOCK (); - n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, - closure, func, data, - g_signal_handler_block); + n_handlers = + signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail, + closure, func, data, + signal_handler_block_unlocked); SIGNAL_UNLOCK (); } @@ -2949,14 +3000,21 @@ g_signal_handlers_block_matched (gpointer instance, * @data: (nullable) (closure closure): The closure data of the handlers' closures. * * Unblocks all handlers on an instance that match a certain selection - * criteria. The criteria mask is passed as an OR-ed combination of - * #GSignalMatchType flags, and the criteria values are passed as arguments. - * Passing at least one of the %G_SIGNAL_MATCH_CLOSURE, %G_SIGNAL_MATCH_FUNC + * criteria. + * + * The criteria mask is passed as a combination of #GSignalMatchType flags, and + * the criteria values are passed as arguments. A handler must match on all + * flags set in @mask to be unblocked (i.e. the match is conjunctive). + * + * Passing at least one of the %G_SIGNAL_MATCH_ID, %G_SIGNAL_MATCH_CLOSURE, + * %G_SIGNAL_MATCH_FUNC * or %G_SIGNAL_MATCH_DATA match flags is required for successful matches. * If no handlers were found, 0 is returned, the number of unblocked handlers * otherwise. The match criteria should not apply to any handlers that are * not currently blocked. * + * Support for %G_SIGNAL_MATCH_ID was added in GLib 2.78. + * * Returns: The number of handlers that matched. */ guint @@ -2973,12 +3031,13 @@ g_signal_handlers_unblock_matched (gpointer instance, g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); - if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) + if (mask & (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) { SIGNAL_LOCK (); - n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, - closure, func, data, - g_signal_handler_unblock); + n_handlers = + signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail, + closure, func, data, + signal_handler_unblock_unlocked); SIGNAL_UNLOCK (); } @@ -2997,14 +3056,20 @@ g_signal_handlers_unblock_matched (gpointer instance, * @data: (nullable) (closure closure): The closure data of the handlers' closures. * * Disconnects all handlers on an instance that match a certain - * selection criteria. The criteria mask is passed as an OR-ed - * combination of #GSignalMatchType flags, and the criteria values are - * passed as arguments. Passing at least one of the - * %G_SIGNAL_MATCH_CLOSURE, %G_SIGNAL_MATCH_FUNC or + * selection criteria. + * + * The criteria mask is passed as a combination of #GSignalMatchType flags, and + * the criteria values are passed as arguments. A handler must match on all + * flags set in @mask to be disconnected (i.e. the match is conjunctive). + * + * Passing at least one of the %G_SIGNAL_MATCH_ID, %G_SIGNAL_MATCH_CLOSURE, + * %G_SIGNAL_MATCH_FUNC or * %G_SIGNAL_MATCH_DATA match flags is required for successful * matches. If no handlers were found, 0 is returned, the number of * disconnected handlers otherwise. * + * Support for %G_SIGNAL_MATCH_ID was added in GLib 2.78. + * * Returns: The number of handlers that matched. */ guint @@ -3021,12 +3086,13 @@ g_signal_handlers_disconnect_matched (gpointer instance, g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); - if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) + if (mask & (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) { SIGNAL_LOCK (); - n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, - closure, func, data, - g_signal_handler_disconnect); + n_handlers = + signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail, + closure, func, data, + signal_handler_disconnect_unlocked); SIGNAL_UNLOCK (); } @@ -3080,7 +3146,7 @@ g_signal_has_handler_pending (gpointer instance, { if (!(node->flags & G_SIGNAL_DETAILED)) { - g_warning ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail); + g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail); SIGNAL_UNLOCK (); return FALSE; } @@ -3149,14 +3215,14 @@ g_signal_emitv (const GValue *instance_and_params, node = LOOKUP_SIGNAL_NODE (signal_id); if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) { - g_warning ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance); + g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance); SIGNAL_UNLOCK (); return; } #ifdef G_ENABLE_DEBUG if (detail && !(node->flags & G_SIGNAL_DETAILED)) { - g_warning ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail); + g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail); SIGNAL_UNLOCK (); return; } @@ -3281,14 +3347,14 @@ g_signal_emit_valist (gpointer instance, node = LOOKUP_SIGNAL_NODE (signal_id); if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) { - g_warning ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance); + g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance); SIGNAL_UNLOCK (); return; } #ifndef G_DISABLE_CHECKS if (detail && !(node->flags & G_SIGNAL_DETAILED)) { - g_warning ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail); + g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail); SIGNAL_UNLOCK (); return; } @@ -3402,7 +3468,16 @@ g_signal_emit_valist (gpointer instance, if (closure != NULL) { + /* + * Coverity doesn’t understand the paired ref/unref here and seems + * to ignore the ref, thus reports every call to g_signal_emit() + * as causing a double-free. That’s incorrect, but I can’t get a + * model file to work for avoiding the false positives, so instead + * comment out the ref/unref when doing static analysis. + */ +#ifndef __COVERITY__ g_object_ref (instance); +#endif _g_closure_invoke_va (closure, return_accu, instance, @@ -3442,7 +3517,7 @@ g_signal_emit_valist (gpointer instance, g_value_unset (&emission_return); else { - g_warning ("%s: %s", G_STRLOC, error); + g_critical ("%s: %s", G_STRLOC, error); g_free (error); /* we purposely leak the value here, it might not be * in a correct state if an error condition occurred @@ -3452,8 +3527,11 @@ g_signal_emit_valist (gpointer instance, TRACE(GOBJECT_SIGNAL_EMIT_END(signal_id, detail, instance, instance_type)); + /* See comment above paired ref above */ +#ifndef __COVERITY__ if (closure != NULL) g_object_unref (instance); +#endif return; } @@ -3477,7 +3555,7 @@ g_signal_emit_valist (gpointer instance, &error); if (error) { - g_warning ("%s: %s", G_STRLOC, error); + g_critical ("%s: %s", G_STRLOC, error); g_free (error); /* we purposely leak the value here, it might not be @@ -3513,7 +3591,7 @@ g_signal_emit_valist (gpointer instance, g_value_unset (&return_value); else { - g_warning ("%s: %s", G_STRLOC, error); + g_critical ("%s: %s", G_STRLOC, error); g_free (error); /* we purposely leak the value here, it might not be @@ -3596,8 +3674,8 @@ g_signal_emit_by_name (gpointer instance, va_end (var_args); } else - g_warning ("%s: signal name '%s' is invalid for instance '%p' of type '%s'", - G_STRLOC, detailed_signal, instance, g_type_name (itype)); + g_critical ("%s: signal name '%s' is invalid for instance '%p' of type '%s'", + G_STRLOC, detailed_signal, instance, g_type_name (itype)); } static gboolean |