Merge branch 'scan-build2-the-false-positives' into 'main'

Squash various false positives from scan-build

Closes #1767

See merge request GNOME/glib!4007
This commit is contained in:
Philip Withnall 2024-04-25 23:55:35 +00:00
commit 640ff0c4da
22 changed files with 121 additions and 104 deletions

View File

@ -741,6 +741,7 @@ scan-build:
--exclude glib/libcharset/ --exclude glib/libcharset/
--exclude gio/xdgmime/ --exclude gio/xdgmime/
-disable-checker deadcode.DeadStores -disable-checker deadcode.DeadStores
--status-bugs
script: script:
- meson setup ${MESON_COMMON_OPTIONS} - meson setup ${MESON_COMMON_OPTIONS}
--werror --werror

View File

@ -5668,7 +5668,7 @@ g_dbus_connection_register_object_with_closures (GDBusConnection *connection
object_path, object_path,
interface_info, interface_info,
&vtable, &vtable,
data, g_steal_pointer (&data),
register_object_free_func, register_object_free_func,
error); error);
} }

View File

@ -199,6 +199,16 @@ name_ref (Name *name)
static void static void
name_unref (Name *name) name_unref (Name *name)
{ {
/* scan-build with clang-17 cant follow the refcounting of `Name` structs
* throughout this file. Probably because there are structures like `NameOwner`
* which cause a ref to be added to a `Name` while they exist, but which dont
* actually have a pointer to the `Name`, so the unref of the `Name` when they
* are freed looks like a double-unref.
*
* So, until the static analysis improves, or we find some way to restructure
* the code, squash the false positive use-after-free or double-unref warnings
* by making this function a no-op to the static analyser. */
#ifndef G_ANALYZER_ANALYZING
g_assert (name->refcount > 0); g_assert (name->refcount > 0);
if (--name->refcount == 0) if (--name->refcount == 0)
{ {
@ -206,6 +216,7 @@ name_unref (Name *name)
g_free (name->name); g_free (name->name);
g_free (name); g_free (name);
} }
#endif
} }
static Name * static Name *

View File

@ -2687,7 +2687,7 @@ prepend_terminal_to_vector (int *argc,
size_t term_argc; size_t term_argc;
char *found_terminal; char *found_terminal;
char **the_argv; char **the_argv;
const char *term_arg; const char *term_arg = NULL;
static const struct { static const struct {
const char *exec; const char *exec;
const char *exec_arg; const char *exec_arg;

View File

@ -310,7 +310,6 @@ read_netlink_messages (GNetworkMonitorNetlink *nl,
struct sockaddr_nl source_sockaddr; struct sockaddr_nl source_sockaddr;
gsize attrlen; gsize attrlen;
guint8 *dest, *gateway, *oif; guint8 *dest, *gateway, *oif;
gboolean retval = TRUE;
iv.buffer = NULL; iv.buffer = NULL;
iv.size = 0; iv.size = 0;
@ -319,26 +318,17 @@ read_netlink_messages (GNetworkMonitorNetlink *nl,
len = g_socket_receive_message (nl->priv->sock, NULL, &iv, 1, len = g_socket_receive_message (nl->priv->sock, NULL, &iv, 1,
NULL, NULL, &flags, NULL, &local_error); NULL, NULL, &flags, NULL, &local_error);
if (len < 0) if (len < 0)
{
retval = FALSE;
goto done; goto done;
}
iv.buffer = g_malloc (len); iv.buffer = g_malloc (len);
iv.size = len; iv.size = len;
len = g_socket_receive_message (nl->priv->sock, &addr, &iv, 1, len = g_socket_receive_message (nl->priv->sock, &addr, &iv, 1,
NULL, NULL, NULL, NULL, &local_error); NULL, NULL, NULL, NULL, &local_error);
if (len < 0) if (len < 0)
{
retval = FALSE;
goto done; goto done;
}
if (!g_socket_address_to_native (addr, &source_sockaddr, sizeof (source_sockaddr), &local_error)) if (!g_socket_address_to_native (addr, &source_sockaddr, sizeof (source_sockaddr), &local_error))
{
retval = FALSE;
goto done; goto done;
}
/* If the sender port id is 0 (not fakeable) then the message is from the kernel */ /* If the sender port id is 0 (not fakeable) then the message is from the kernel */
if (source_sockaddr.nl_pid != 0) if (source_sockaddr.nl_pid != 0)
@ -353,7 +343,6 @@ read_netlink_messages (GNetworkMonitorNetlink *nl,
G_IO_ERROR, G_IO_ERROR,
G_IO_ERROR_PARTIAL_INPUT, G_IO_ERROR_PARTIAL_INPUT,
"netlink message was truncated; shouldn't happen..."); "netlink message was truncated; shouldn't happen...");
retval = FALSE;
goto done; goto done;
} }
@ -419,7 +408,6 @@ read_netlink_messages (GNetworkMonitorNetlink *nl,
"netlink error: %s", "netlink error: %s",
g_strerror (-e->error)); g_strerror (-e->error));
} }
retval = FALSE;
goto done; goto done;
default: default:
@ -428,7 +416,6 @@ read_netlink_messages (GNetworkMonitorNetlink *nl,
G_IO_ERROR_INVALID_DATA, G_IO_ERROR_INVALID_DATA,
"unexpected netlink message %d", "unexpected netlink message %d",
msg->nlmsg_type); msg->nlmsg_type);
retval = FALSE;
goto done; goto done;
} }
} }
@ -437,13 +424,18 @@ read_netlink_messages (GNetworkMonitorNetlink *nl,
g_free (iv.buffer); g_free (iv.buffer);
g_clear_object (&addr); g_clear_object (&addr);
if (!retval && nl->priv->dump_networks) if (local_error != NULL && nl->priv->dump_networks)
finish_dump (nl); finish_dump (nl);
if (local_error) if (local_error != NULL)
{
g_propagate_prefixed_error (error, local_error, "Error on netlink socket: "); g_propagate_prefixed_error (error, local_error, "Error on netlink socket: ");
return FALSE;
return retval; }
else
{
return TRUE;
}
} }
static void static void

View File

@ -285,14 +285,10 @@ g_proxy_address_enumerator_next (GSocketAddressEnumerator *enumerator,
{ {
dest_hostname = g_strdup (priv->dest_hostname); dest_hostname = g_strdup (priv->dest_hostname);
} }
dest_protocol = g_uri_parse_scheme (priv->dest_uri);
if (!G_IS_INET_SOCKET_ADDRESS (priv->proxy_address)) g_assert (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address));
{
g_free (dest_hostname); dest_protocol = g_uri_parse_scheme (priv->dest_uri);
g_free (dest_protocol);
}
g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address), NULL);
inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address); inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
inetaddr = g_inet_socket_address_get_address (inetsaddr); inetaddr = g_inet_socket_address_get_address (inetsaddr);
@ -363,7 +359,6 @@ return_result (GTask *task)
{ {
GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task); GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
GSocketAddress *result; GSocketAddress *result;
gboolean is_inet_socket_address;
if (strcmp ("direct", priv->proxy_type) == 0) if (strcmp ("direct", priv->proxy_type) == 0)
{ {
@ -395,13 +390,7 @@ return_result (GTask *task)
} }
dest_protocol = g_uri_parse_scheme (priv->dest_uri); dest_protocol = g_uri_parse_scheme (priv->dest_uri);
is_inet_socket_address = G_IS_INET_SOCKET_ADDRESS (priv->proxy_address); g_assert (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address));
if (!is_inet_socket_address)
{
g_free (dest_hostname);
g_free (dest_protocol);
}
g_return_if_fail (is_inet_socket_address);
inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address); inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
inetaddr = g_inet_socket_address_get_address (inetsaddr); inetaddr = g_inet_socket_address_get_address (inetsaddr);

View File

@ -285,6 +285,7 @@ g_srv_target_list_sort (GList *targets)
val = g_random_int_range (0, sum + 1); val = g_random_int_range (0, sum + 1);
for (t = targets; ; t = t->next) for (t = targets; ; t = t->next)
{ {
g_assert (t != NULL && t->data != NULL);
weight = ((GSrvTarget *)t->data)->weight; weight = ((GSrvTarget *)t->data)->weight;
if (weight >= val) if (weight >= val)
break; break;

View File

@ -2079,7 +2079,7 @@ mount_monitor_start (void)
if (proc_mounts_channel == NULL) if (proc_mounts_channel == NULL)
proc_mounts_channel = g_io_channel_new_file (mtab_path, "r", &error); proc_mounts_channel = g_io_channel_new_file (mtab_path, "r", &error);
if (proc_mounts_channel == NULL) if (error != NULL)
{ {
g_warning ("Error creating IO channel for %s: %s (%s, %d)", mtab_path, g_warning ("Error creating IO channel for %s: %s (%s, %d)", mtab_path,
error->message, g_quark_to_string (error->domain), error->code); error->message, g_quark_to_string (error->domain), error->code);

View File

@ -543,7 +543,7 @@ get_and_check_serialization (GVariant *value)
/* First check that the serialization to the D-Bus wire format is correct - do this for both byte orders */ /* First check that the serialization to the D-Bus wire format is correct - do this for both byte orders */
for (n = 0; n < 2; n++) for (n = 0; n < 2; n++)
{ {
GDBusMessageByteOrder byte_order; GDBusMessageByteOrder byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
switch (n) switch (n)
{ {
case 0: case 0:

View File

@ -245,10 +245,15 @@ cache_magic_compare_to_data (XdgMimeCache *cache,
size_t len, size_t len,
int *prio) int *prio)
{ {
xdg_uint32_t priority = GET_UINT32 (cache->buffer, offset); xdg_uint32_t priority, mimetype_offset, n_matchlets, matchlet_offset;
xdg_uint32_t mimetype_offset = GET_UINT32 (cache->buffer, offset + 4);
xdg_uint32_t n_matchlets = GET_UINT32 (cache->buffer, offset + 8); assert (cache->buffer != NULL);
xdg_uint32_t matchlet_offset = GET_UINT32 (cache->buffer, offset + 12);
priority = GET_UINT32 (cache->buffer, offset);
mimetype_offset = GET_UINT32 (cache->buffer, offset + 4);
n_matchlets = GET_UINT32 (cache->buffer, offset + 8);
matchlet_offset = GET_UINT32 (cache->buffer, offset + 12);
if (OUT_OF_BOUNDS (matchlet_offset, n_matchlets, 32, cache->size)) if (OUT_OF_BOUNDS (matchlet_offset, n_matchlets, 32, cache->size))
return NULL; return NULL;
@ -280,6 +285,8 @@ cache_magic_lookup_data (XdgMimeCache *cache,
xdg_uint32_t j; xdg_uint32_t j;
assert (cache->buffer != NULL);
*prio = 0; *prio = 0;
list_offset = GET_UINT32 (cache->buffer, 24); list_offset = GET_UINT32 (cache->buffer, 24);

View File

@ -670,6 +670,9 @@ parse_type_internal (GIIrModule *module,
type->is_pointer = TRUE; type->is_pointer = TRUE;
str += strlen ("Error"); str += strlen ("Error");
/* Silence a scan-build false positive */
g_assert (str != NULL);
if (*str == '<') if (*str == '<')
{ {
char *tmp, *end; char *tmp, *end;

View File

@ -3104,7 +3104,7 @@ format_number (GString *str,
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9" "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
}; };
const gchar * const *digits = ascii_digits; const gchar * const *digits = ascii_digits;
const gchar *tmp[10]; const gchar *tmp[10] = { '\0', };
gint i = 0; gint i = 0;
#ifdef HAVE_LANGINFO_OUTDIGIT #ifdef HAVE_LANGINFO_OUTDIGIT
static GMutex alt_digits_mutex; static GMutex alt_digits_mutex;

View File

@ -32,6 +32,7 @@
#include "garray.h" #include "garray.h"
#include "gmem.h" #include "gmem.h"
#include "gmessages.h"
#include "gstring.h" #include "gstring.h"
#include "gstrfuncs.h" #include "gstrfuncs.h"
#include "glibintl.h" #include "glibintl.h"
@ -667,6 +668,8 @@ g_hostname_to_unicode (const gchar *hostname)
gssize llen; gssize llen;
gsize hostname_max_length_bytes = get_hostname_max_length_bytes (); gsize hostname_max_length_bytes = get_hostname_max_length_bytes ();
g_return_val_if_fail (hostname != NULL, NULL);
/* See the comment at the top of g_hostname_to_ascii(). */ /* See the comment at the top of g_hostname_to_ascii(). */
if (hostname_max_length_bytes <= G_MAXSIZE / 4 && if (hostname_max_length_bytes <= G_MAXSIZE / 4 &&
strlen_greater_than (hostname, 4 * MAX (255, hostname_max_length_bytes))) strlen_greater_than (hostname, 4 * MAX (255, hostname_max_length_bytes)))

View File

@ -1732,6 +1732,7 @@ node_get_by_pos (GSequenceNode *node,
{ {
node = node->left; node = node->left;
} }
g_assert (node != NULL);
} }
return node; return node;

View File

@ -4308,7 +4308,9 @@ g_test_log_dump (GTestLogMsg *msg,
gstring_append_int (gstring, 0); /* reserved */ gstring_append_int (gstring, 0); /* reserved */
for (ui = 0; ui < msg->n_strings; ui++) for (ui = 0; ui < msg->n_strings; ui++)
{ {
guint l = strlen (msg->strings[ui]); guint l;
g_assert (msg->strings[ui] != NULL);
l = strlen (msg->strings[ui]);
gstring_append_int (gstring, l); gstring_append_int (gstring, l);
g_string_append_len (gstring, msg->strings[ui], l); g_string_append_len (gstring, msg->strings[ui], l);
} }

View File

@ -280,6 +280,7 @@ again:
GTimeZone * GTimeZone *
g_time_zone_ref (GTimeZone *tz) g_time_zone_ref (GTimeZone *tz)
{ {
g_return_val_if_fail (tz != NULL, NULL);
g_assert (tz->ref_count > 0); g_assert (tz->ref_count > 0);
g_atomic_int_inc (&tz->ref_count); g_atomic_int_inc (&tz->ref_count);

View File

@ -26,6 +26,7 @@
#include "gunicode.h" #include "gunicode.h"
#include "gunidecomp.h" #include "gunidecomp.h"
#include "gmem.h" #include "gmem.h"
#include "gtestutils.h"
#include "gunicomp.h" #include "gunicomp.h"
#include "gunicodeprivate.h" #include "gunicodeprivate.h"
@ -428,8 +429,9 @@ _g_utf8_normalize_wc (const gchar *str,
wc_buffer[n_wc++] = wc; wc_buffer[n_wc++] = wc;
} }
if (n_wc > 0) /* Each code path above *must* have appended at least gunichar to wc_buffer. */
{ g_assert (n_wc > old_n_wc);
cc = COMBINING_CLASS (wc_buffer[old_n_wc]); cc = COMBINING_CLASS (wc_buffer[old_n_wc]);
if (cc == 0) if (cc == 0)
@ -437,7 +439,6 @@ _g_utf8_normalize_wc (const gchar *str,
g_unicode_canonical_ordering (wc_buffer + last_start, n_wc - last_start); g_unicode_canonical_ordering (wc_buffer + last_start, n_wc - last_start);
last_start = old_n_wc; last_start = old_n_wc;
} }
}
p = g_utf8_next_char (p); p = g_utf8_next_char (p);
} }

View File

@ -904,6 +904,8 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
if (value.size != 0 && offsets.length == 0) if (value.size != 0 && offsets.length == 0)
return FALSE; return FALSE;
g_assert (value.size != 0 || offsets.length == 0);
child.type_info = g_variant_type_info_element (value.type_info); child.type_info = g_variant_type_info_element (value.type_info);
g_variant_type_info_query (child.type_info, &alignment, NULL); g_variant_type_info_query (child.type_info, &alignment, NULL);
child.depth = value.depth + 1; child.depth = value.depth + 1;

View File

@ -4620,7 +4620,7 @@ g_variant_format_string_scan_type (const gchar *string,
const gchar **endptr) const gchar **endptr)
{ {
const gchar *my_end; const gchar *my_end;
gchar *dest; gsize i;
gchar *new; gchar *new;
if (endptr == NULL) if (endptr == NULL)
@ -4629,16 +4629,19 @@ g_variant_format_string_scan_type (const gchar *string,
if (!g_variant_format_string_scan (string, limit, endptr)) if (!g_variant_format_string_scan (string, limit, endptr))
return NULL; return NULL;
dest = new = g_malloc (*endptr - string + 1); new = g_malloc (*endptr - string + 1);
i = 0;
while (string != *endptr) while (string != *endptr)
{ {
if (*string != '@' && *string != '&' && *string != '^') if (*string != '@' && *string != '&' && *string != '^')
*dest++ = *string; new[i++] = *string;
string++; string++;
} }
*dest = '\0'; new[i++] = '\0';
return (GVariantType *) G_VARIANT_TYPE (new); g_assert (g_variant_type_string_is_valid (new));
return (GVariantType *) new;
} }
static gboolean static gboolean

View File

@ -106,7 +106,7 @@ typedef union {
gint vint; gint vint;
} ClosureInt; } ClosureInt;
#define CHANGE_FIELD(_closure, _field, _OP, _value, _must_set, _SET_OLD, _SET_NEW) \ #define ATOMIC_CHANGE_FIELD(_closure, _field, _OP, _value, _must_set, _SET_OLD, _SET_NEW) \
G_STMT_START { \ G_STMT_START { \
ClosureInt *cunion = (ClosureInt*) _closure; \ ClosureInt *cunion = (ClosureInt*) _closure; \
gint new_int, old_int, success; \ gint new_int, old_int, success; \
@ -123,21 +123,12 @@ G_STMT_START {
while (!success && _must_set); \ while (!success && _must_set); \
} G_STMT_END } G_STMT_END
#define SWAP(_closure, _field, _value, _oldv) CHANGE_FIELD (_closure, _field, =, _value, TRUE, *(_oldv) =, (void) ) #define ATOMIC_SWAP(_closure, _field, _value, _oldv) ATOMIC_CHANGE_FIELD (_closure, _field, =, _value, TRUE, *(_oldv) =, (void) )
#define SET(_closure, _field, _value) CHANGE_FIELD (_closure, _field, =, _value, TRUE, (void), (void) ) #define ATOMIC_SET(_closure, _field, _value) ATOMIC_CHANGE_FIELD (_closure, _field, =, _value, TRUE, (void), (void) )
#define INC(_closure, _field) CHANGE_FIELD (_closure, _field, +=, 1, TRUE, (void), (void) ) #define ATOMIC_INC(_closure, _field) ATOMIC_CHANGE_FIELD (_closure, _field, +=, 1, TRUE, (void), (void) )
#define INC_ASSIGN(_closure, _field, _newv) CHANGE_FIELD (_closure, _field, +=, 1, TRUE, (void), *(_newv) = ) #define ATOMIC_INC_ASSIGN(_closure, _field, _newv) ATOMIC_CHANGE_FIELD (_closure, _field, +=, 1, TRUE, (void), *(_newv) = )
#define DEC(_closure, _field) CHANGE_FIELD (_closure, _field, -=, 1, TRUE, (void), (void) ) #define ATOMIC_DEC(_closure, _field) ATOMIC_CHANGE_FIELD (_closure, _field, -=, 1, TRUE, (void), (void) )
#define DEC_ASSIGN(_closure, _field, _newv) CHANGE_FIELD (_closure, _field, -=, 1, TRUE, (void), *(_newv) = ) #define ATOMIC_DEC_ASSIGN(_closure, _field, _newv) ATOMIC_CHANGE_FIELD (_closure, _field, -=, 1, TRUE, (void), *(_newv) = )
#if 0 /* for non-thread-safe closures */
#define SWAP(cl,f,v,o) (void) (*(o) = cl->f, cl->f = v)
#define SET(cl,f,v) (void) (cl->f = v)
#define INC(cl,f) (void) (cl->f += 1)
#define INC_ASSIGN(cl,f,n) (void) (cl->f += 1, *(n) = cl->f)
#define DEC(cl,f) (void) (cl->f -= 1)
#define DEC_ASSIGN(cl,f,n) (void) (cl->f -= 1, *(n) = cl->f)
#endif
enum { enum {
FNOTIFY, FNOTIFY,
@ -225,8 +216,8 @@ g_closure_new_simple (guint sizeof_closure,
closure = (GClosure *) (allocated + private_size); closure = (GClosure *) (allocated + private_size);
SET (closure, ref_count, 1); ATOMIC_SET (closure, ref_count, 1);
SET (closure, floating, TRUE); ATOMIC_SET (closure, floating, TRUE);
closure->data = data; closure->data = data;
return closure; return closure;
@ -261,7 +252,7 @@ closure_invoke_notifiers (GClosure *closure,
while (closure->n_fnotifiers) while (closure->n_fnotifiers)
{ {
guint n; guint n;
DEC_ASSIGN (closure, n_fnotifiers, &n); ATOMIC_DEC_ASSIGN (closure, n_fnotifiers, &n);
ndata = closure->notifiers + CLOSURE_N_MFUNCS (closure) + n; ndata = closure->notifiers + CLOSURE_N_MFUNCS (closure) + n;
closure->marshal = (GClosureMarshal) ndata->notify; closure->marshal = (GClosureMarshal) ndata->notify;
@ -272,11 +263,11 @@ closure_invoke_notifiers (GClosure *closure,
closure->data = NULL; closure->data = NULL;
break; break;
case INOTIFY: case INOTIFY:
SET (closure, in_inotify, TRUE); ATOMIC_SET (closure, in_inotify, TRUE);
while (closure->n_inotifiers) while (closure->n_inotifiers)
{ {
guint n; guint n;
DEC_ASSIGN (closure, n_inotifiers, &n); ATOMIC_DEC_ASSIGN (closure, n_inotifiers, &n);
ndata = closure->notifiers + CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers + n; ndata = closure->notifiers + CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers + n;
closure->marshal = (GClosureMarshal) ndata->notify; closure->marshal = (GClosureMarshal) ndata->notify;
@ -285,7 +276,7 @@ closure_invoke_notifiers (GClosure *closure,
} }
closure->marshal = NULL; closure->marshal = NULL;
closure->data = NULL; closure->data = NULL;
SET (closure, in_inotify, FALSE); ATOMIC_SET (closure, in_inotify, FALSE);
break; break;
case PRE_NOTIFY: case PRE_NOTIFY:
i = closure->n_guards; i = closure->n_guards;
@ -429,7 +420,7 @@ g_closure_add_marshal_guards (GClosure *closure,
closure->notifiers[i].notify = pre_marshal_notify; closure->notifiers[i].notify = pre_marshal_notify;
closure->notifiers[i + 1].data = post_marshal_data; closure->notifiers[i + 1].data = post_marshal_data;
closure->notifiers[i + 1].notify = post_marshal_notify; closure->notifiers[i + 1].notify = post_marshal_notify;
INC (closure, n_guards); ATOMIC_INC (closure, n_guards);
} }
/** /**
@ -466,7 +457,7 @@ g_closure_add_finalize_notifier (GClosure *closure,
i = CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers; i = CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers;
closure->notifiers[i].data = notify_data; closure->notifiers[i].data = notify_data;
closure->notifiers[i].notify = notify_func; closure->notifiers[i].notify = notify_func;
INC (closure, n_fnotifiers); ATOMIC_INC (closure, n_fnotifiers);
} }
/** /**
@ -497,7 +488,7 @@ g_closure_add_invalidate_notifier (GClosure *closure,
i = CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers + closure->n_inotifiers; i = CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers + closure->n_inotifiers;
closure->notifiers[i].data = notify_data; closure->notifiers[i].data = notify_data;
closure->notifiers[i].notify = notify_func; closure->notifiers[i].notify = notify_func;
INC (closure, n_inotifiers); ATOMIC_INC (closure, n_inotifiers);
} }
static inline gboolean static inline gboolean
@ -511,7 +502,7 @@ closure_try_remove_inotify (GClosure *closure,
for (ndata = nlast + 1 - closure->n_inotifiers; ndata <= nlast; ndata++) for (ndata = nlast + 1 - closure->n_inotifiers; ndata <= nlast; ndata++)
if (ndata->notify == notify_func && ndata->data == notify_data) if (ndata->notify == notify_func && ndata->data == notify_data)
{ {
DEC (closure, n_inotifiers); ATOMIC_DEC (closure, n_inotifiers);
if (ndata < nlast) if (ndata < nlast)
*ndata = *nlast; *ndata = *nlast;
@ -531,7 +522,7 @@ closure_try_remove_fnotify (GClosure *closure,
for (ndata = nlast + 1 - closure->n_fnotifiers; ndata <= nlast; ndata++) for (ndata = nlast + 1 - closure->n_fnotifiers; ndata <= nlast; ndata++)
if (ndata->notify == notify_func && ndata->data == notify_data) if (ndata->notify == notify_func && ndata->data == notify_data)
{ {
DEC (closure, n_fnotifiers); ATOMIC_DEC (closure, n_fnotifiers);
if (ndata < nlast) if (ndata < nlast)
*ndata = *nlast; *ndata = *nlast;
if (closure->n_inotifiers) if (closure->n_inotifiers)
@ -561,12 +552,23 @@ g_closure_ref (GClosure *closure)
g_return_val_if_fail (closure->ref_count > 0, NULL); g_return_val_if_fail (closure->ref_count > 0, NULL);
g_return_val_if_fail (closure->ref_count < CLOSURE_MAX_REF_COUNT, NULL); g_return_val_if_fail (closure->ref_count < CLOSURE_MAX_REF_COUNT, NULL);
INC_ASSIGN (closure, ref_count, &new_ref_count); ATOMIC_INC_ASSIGN (closure, ref_count, &new_ref_count);
g_return_val_if_fail (new_ref_count > 1, NULL); g_return_val_if_fail (new_ref_count > 1, NULL);
return closure; return closure;
} }
static void
closure_invalidate_internal (GClosure *closure)
{
gboolean was_invalid;
ATOMIC_SWAP (closure, is_invalid, TRUE, &was_invalid);
/* invalidate only once */
if (!was_invalid)
closure_invoke_notifiers (closure, INOTIFY);
}
/** /**
* g_closure_invalidate: * g_closure_invalidate:
* @closure: #GClosure to invalidate * @closure: #GClosure to invalidate
@ -594,12 +596,8 @@ g_closure_invalidate (GClosure *closure)
if (!closure->is_invalid) if (!closure->is_invalid)
{ {
gboolean was_invalid;
g_closure_ref (closure); /* preserve floating flag */ g_closure_ref (closure); /* preserve floating flag */
SWAP (closure, is_invalid, TRUE, &was_invalid); closure_invalidate_internal (closure);
/* invalidate only once */
if (!was_invalid)
closure_invoke_notifiers (closure, INOTIFY);
g_closure_unref (closure); g_closure_unref (closure);
} }
} }
@ -622,10 +620,11 @@ g_closure_unref (GClosure *closure)
g_return_if_fail (closure != NULL); g_return_if_fail (closure != NULL);
g_return_if_fail (closure->ref_count > 0); g_return_if_fail (closure->ref_count > 0);
if (closure->ref_count == 1) /* last unref, invalidate first */ /* last unref, invalidate first */
g_closure_invalidate (closure); if (closure->ref_count == 1 && !closure->is_invalid)
closure_invalidate_internal (closure);
DEC_ASSIGN (closure, ref_count, &new_ref_count); ATOMIC_DEC_ASSIGN (closure, ref_count, &new_ref_count);
if (new_ref_count == 0) if (new_ref_count == 0)
{ {
@ -719,7 +718,7 @@ g_closure_sink (GClosure *closure)
if (closure->floating) if (closure->floating)
{ {
gboolean was_floating; gboolean was_floating;
SWAP (closure, floating, FALSE, &was_floating); ATOMIC_SWAP (closure, floating, FALSE, &was_floating);
/* unref floating flag only once */ /* unref floating flag only once */
if (was_floating) if (was_floating)
g_closure_unref (closure); g_closure_unref (closure);
@ -818,7 +817,7 @@ g_closure_invoke (GClosure *closure,
g_return_if_fail (closure->marshal || real_closure->meta_marshal); g_return_if_fail (closure->marshal || real_closure->meta_marshal);
SET (closure, in_marshal, TRUE); ATOMIC_SET (closure, in_marshal, TRUE);
if (real_closure->meta_marshal) if (real_closure->meta_marshal)
{ {
marshal_data = real_closure->meta_marshal_data; marshal_data = real_closure->meta_marshal_data;
@ -838,7 +837,7 @@ g_closure_invoke (GClosure *closure,
marshal_data); marshal_data);
if (!in_marshal) if (!in_marshal)
closure_invoke_notifiers (closure, POST_NOTIFY); closure_invoke_notifiers (closure, POST_NOTIFY);
SET (closure, in_marshal, in_marshal); ATOMIC_SET (closure, in_marshal, in_marshal);
} }
g_closure_unref (closure); g_closure_unref (closure);
} }
@ -881,7 +880,7 @@ _g_closure_invoke_va (GClosure *closure,
g_return_if_fail (closure->marshal || real_closure->meta_marshal); g_return_if_fail (closure->marshal || real_closure->meta_marshal);
SET (closure, in_marshal, TRUE); ATOMIC_SET (closure, in_marshal, TRUE);
if (real_closure->va_meta_marshal) if (real_closure->va_meta_marshal)
{ {
marshal_data = real_closure->meta_marshal_data; marshal_data = real_closure->meta_marshal_data;
@ -901,7 +900,7 @@ _g_closure_invoke_va (GClosure *closure,
n_params, param_types); n_params, param_types);
if (!in_marshal) if (!in_marshal)
closure_invoke_notifiers (closure, POST_NOTIFY); closure_invoke_notifiers (closure, POST_NOTIFY);
SET (closure, in_marshal, in_marshal); ATOMIC_SET (closure, in_marshal, in_marshal);
} }
g_closure_unref (closure); g_closure_unref (closure);
} }
@ -1011,7 +1010,7 @@ g_cclosure_new_swap (GCallback callback_func,
if (destroy_data) if (destroy_data)
g_closure_add_finalize_notifier (closure, user_data, destroy_data); g_closure_add_finalize_notifier (closure, user_data, destroy_data);
((GCClosure*) closure)->callback = (gpointer) callback_func; ((GCClosure*) closure)->callback = (gpointer) callback_func;
SET (closure, derivative_flag, TRUE); ATOMIC_SET (closure, derivative_flag, TRUE);
return closure; return closure;
} }

View File

@ -5606,6 +5606,7 @@ _weak_ref_set (GWeakRef *weak_ref,
if (new_object) if (new_object)
{ {
#if G_ENABLE_DEBUG #if G_ENABLE_DEBUG
g_assert (new_wrdata != NULL);
g_assert (weak_ref_data_list_find (new_wrdata, weak_ref) < 0); g_assert (weak_ref_data_list_find (new_wrdata, weak_ref) < 0);
#endif #endif
if (g_atomic_int_get (&new_object->ref_count) < 1) if (g_atomic_int_get (&new_object->ref_count) < 1)

View File

@ -1197,13 +1197,13 @@ type_data_make_W (TypeNode *node,
if (value_table->lcopy_format) if (value_table->lcopy_format)
strcat (p, value_table->lcopy_format); strcat (p, value_table->lcopy_format);
} }
node->data->common.value_table = vtable; node->data->common.value_table = vtable;
g_assert (node->data->common.value_table != NULL); /* paranoid */
node->mutatable_check_cache = (node->data->common.value_table->value_init != NULL && node->mutatable_check_cache = (node->data->common.value_table->value_init != NULL &&
!((G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_ABSTRACT) & !((G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_ABSTRACT) &
GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags)))); GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))));
g_assert (node->data->common.value_table != NULL); /* paranoid */
g_atomic_int_set ((int *) &node->ref_count, 1); g_atomic_int_set ((int *) &node->ref_count, 1);
} }