31580 Commits

Author SHA1 Message Date
Thomas Haller
a2da296230 gobject: optimize notify-queue handling for a single freeze
When we set a property we usually tend to freeze the queue notification
and thaw it at the end. This always requires a per-object allocation
that is necessary to track the freeze count and frozen properties.

But there are cases cases, where we freeze only a single time and never
add a property to unfreeze. In such cases, we can avoid allocating a new
GObjectNotifyQueue instance.

Optimize for that case by initially adding a global, immutable sentinel
pointer "notify_queue_empty". Only when requiring a per-object queue,
allocate one.

This can be useful before calling dispose(). While there are probably
dispose functions that still try to set properties on the object (which
is the main reason to freeze the notification), most probably don't. In
this case, we can avoid allocating the memory during g_object_unref().

Another such case is object construction. If the object has no construct
properties and the user didn't specify any properties during
g_object_new(), we may well freeze the object but never add properties
to it. In that case too, we can get away without ever allocating the
GObjectNotifyQueue.
2025-04-03 18:13:39 +02:00
Thomas Haller
e0ccac2fff gobject: rework freezing once during object initialization
During object initialization, we may want to freeze the notifications,
but only do so once (and once unfreeze at the end).

Rework how that was done. We can avoid an additional GData lookup.
2025-04-03 18:08:39 +02:00
Thomas Haller
08ebff5b0f gobject: don't pass around the GObjectNotifyQueue instance
By now, GObjectNotifyQueue gets reallocated. So quite possibly if we
keep the queue, it is a dangling pointer.

That is error prone, but it's also unnecessary. All we need to know is
whether we bumped the freeze count and need to unfreeze. The queue
itself was not useful, because we anyway must take a lock (via
g_datalist_id_update_atomic()) to do anything with it.

Instead, use a nqueue_is_frozen boolean variable.
2025-04-03 18:08:39 +02:00
Thomas Haller
c9306a9b25 gobject: rework GObjectNotifyQueue to not use GSList
GSList is almost in all use cases a bad choice. It's bad for locality
and requires a heap allocation per entry.

Instead, use an array, and grow the buffer exponentially via realloc().

Now, that we use g_datalist_id_update_atomic(), it is also easy to
update the pointer. Hence, the GObjectNotifyQueue struct does not point
to an array of pspecs. Instead the entire GObjectNotifyQueue itself gets
reallocated, thus saving one heap allocation for the separate head
structure.
2025-04-03 18:08:39 +02:00
Thomas Haller
a07a3351b3 gobject: drop OPTIONAL_BIT_LOCK_NOTIFY lock
Now all accesses to quark_notify_queue are guarded by the GData lock.
Several non-trivial operations are implemented via
g_datalist_id_update_atomic().

The OPTIONAL_BIT_LOCK_NOTIFY lock is thus unnecessary and can be dropped.

Note that with the move to g_datalist_id_update_atomic(), we now
potentially do more work while holding the GData lock (e.g. some code
paths allocation additional memory). But note that
g_datalist_id_set_data() already has code paths where it must allocate
memory to track the GDataElt. Also, most objects are not used in
parallel, so holding the per-object (per-GData) lock longer does not
affect them. Also, many operations also require a object_bit_lock(), so
it seems very unlikely that you really could achieve higher parallelism
by taking more locks (and minimizing the time to hold the GData lock).
On the contrary, taking one lock less and doing all the work there is
beneficial.
2025-04-03 18:08:38 +02:00
Thomas Haller
36953b29dd gobject: rework g_object_notify_queue_add() to use g_datalist_id_update_atomic()
The goal is to drop OPTIONAL_BIT_LOCK_NOTIFY lock. This is one step.
Move code inside g_datalist_id_update_atomic().
2025-04-03 18:07:36 +02:00
Thomas Haller
f786844898 gobject: rework g_object_notify_queue_thaw() to use g_datalist_id_update_atomic()
The goal is to drop OPTIONAL_BIT_LOCK_NOTIFY lock. This is one step.
Move code inside g_datalist_id_update_atomic().
2025-04-03 18:07:36 +02:00
Thomas Haller
54e2edc70f gobject: rework g_object_notify_queue_freeze() to use g_datalist_id_update_atomic()
A common pattern is to look whether a GData entry exists, and if it
doesn't, add it.

For that, we currently always must take a OPTIONAL_BIT_LOCK_NOTIFY lock.

This can be avoided, because GData already uses an internal mutex. By
using g_datalist_id_update_atomic(), we can perform all relevant
operations while holding that mutex.

Move functionality from g_object_notify_queue_freeze() inside
g_datalist_id_update_atomic().

The goal will be to drop the OPTIONAL_BIT_LOCK_NOTIFY lock in a later
commit.
2025-04-03 18:07:36 +02:00
Philip Withnall
c4af0f0bd0 Merge branch 'th/gdataset-cleanup' into 'main'
[th/gdataset-cleanup] minor cleanups of gdataset

See merge request GNOME/glib!4520
2025-04-03 15:25:20 +00:00
Philip Withnall
1bf83890a0 Merge branch '1250-socket-listener-leak' into 'main'
gsocketlistener: Fix IPv4 listen() error handling

Closes #1250

See merge request GNOME/glib!643
2025-04-03 15:15:59 +00:00
Philip Withnall
f31c072005 Merge branch 'pgriffis/gresolver-onlyloopback' into 'main'
threadedresolver: Return valid addresses when only having loopback interfaces

Closes #3641

See merge request GNOME/glib!4566
2025-04-03 15:09:58 +00:00
Philip Withnall
792c4505e0 Merge branch 'th/gobj-closure-array-atomic' into 'main'
[th/gobj-closure-array-atomic] use g_datalist_id_update_atomic() for array of closure watches

See merge request GNOME/glib!4536
2025-04-03 15:09:06 +00:00
Philip Withnall
56515e93a7 Merge branch '3527-Wshorten-64-to-32' into 'main'
Fix various -Wshorten-64-to-32 warnings

See merge request GNOME/glib!4387
2025-04-03 15:07:09 +00:00
Philip Withnall
eaa7e5bdfd
2.84.1
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2.84.1
2025-04-03 15:38:51 +01:00
Philip Withnall
d854836aff
girparser: Fix a strict-aliasing warning with g_clear_pointer()
Casting the type for a `g_clear_pointer()` call breaks strict aliasing
rules.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2025-04-03 15:38:45 +01:00
Philip Withnall
29e27d8dcd Merge branch 'cancellable-connection-fixes' into 'main'
cancellable: Fix connect and disconnect references handling

Closes #3642 and #3643

See merge request GNOME/glib!4573
2025-04-03 13:55:49 +00:00
Marco Trevisan (Treviño)
a2f98c86ff gio/cancellable: Never call toggle notify callback in locked state
We had code to avoid that we could call a toggle "up" notification
callback in locked state, but this was not covering the case in which
the cancellable second to last reference was removed in its cancellation
callback.

In fact, in such case we end up going from 2 -> 1 references during the
signal callback call and this leads to calling the toggle notify
callback in locked state.

To prevent this, add an even further reference before calling the
callback (in locked state, but there's no risk that a toggle-up
notification happens now), and drop it once unlocked again.
2025-04-03 15:22:16 +02:00
Marco Trevisan (Treviño)
ec2fee555f gio/cancellable: Do not call data destroy function while locked
If when calling g_cancellable_connect() the cancellable was already
cancelled we could have ended up in calling the data cleanup
function while the cancellable lock was held.

This is likely not an issue, but it's still better not to do it,
so protect the code against it
2025-04-03 15:22:16 +02:00
Marco Trevisan (Treviño)
c6ace7aaf7 gio/cancellable: Fix comments for g_cancellable_connect()
We had wrong comments, in particular:

  @callback is called exactly once each time @cancellable is cancelled,
  either directly at the time of the connect if @cancellable is already
  cancelled, or when @cancellable is cancelled in some thread.
  In case the cancellable is reset via [method@Gio.Cancellable.reset]
  then the callback can be called again if the @cancellable is cancelled

This is not true if `@cancellable` is already cancelled because then the
callback will be thrown away, and will not be called for subsequent
cancellations.

  Since GLib 2.40, the lock protecting @cancellable is not held when
  @callback is invoked.  This lifts a restriction in place for
  earlier GLib versions which now makes it easier to write cleanup
  code that unconditionally invokes e.g. g_cancellable_cancel().

As per commit 3a07b2abd4006 this section needs some amending since
it's not true anymore, as the GCancellable's mutex is held when `@callback` is
invoked. However this happens in a way that it's still safe to call most
of the GCancellable API.

Closes: #3642
2025-04-03 15:22:16 +02:00
Philip Withnall
7ea714e658 Merge branch 'wip/3v1n0/sanitizer-memory-fixes' into 'main'
Memory sanitizer fixes

See merge request GNOME/glib!4484
2025-04-03 13:04:05 +00:00
Marco Trevisan (Treviño)
49680afd5c gio/cancellable: Always add reference while emitting cancelled signal
When a non-cancelled cancellable ::cancelled signal callback is called
the cancellable has enough references so that it can be unreferenced on
the callback itself. However this doesn't happen if the cancellable has
been already cancelled at the moment we connect to it.

To prevent this, add a temporary reference before calling the signal
callback.

Note that we do this also if the callback has not been already cancelled
to prevent that we may end up calling a toggle-notify callback while we
are locked.

Add tests

Closes: #3643
2025-04-03 14:48:57 +02:00
Marco Trevisan (Treviño)
7432441581 test/cancellable: Check that a cancellable can be unreffed on callback
This works when the cancellable has not been cancelled yet.
2025-04-03 14:48:56 +02:00
Marco Trevisan (Treviño)
03dcf4cdc3 glib/messages: Avoid warning on potentially uninitialized value
In function ‘memmem_with_end_pointer’,
    inlined from ‘domain_found’ at ../glib/gmessages.c:2695:16,
    inlined from ‘should_drop_message’ at ../glib/gmessages.c:2802:35:
../glib/gmessages.c:2674:19: warning: ‘log_domain_length’ may be used
    uninitialized [-Wmaybe-uninitialized]
 2674 | #define my_memmem memmem
      |                   ^
../glib/gmessages.c:2683:10: note: in expansion of macro ‘my_memmem’
 2683 |   return my_memmem (haystack, (const char *) haystack_end - (const char *) haystack, needle, needle_len);
      |          ^~~~~~~~~
../glib/gmessages.c: In function ‘should_drop_message’:
../glib/gmessages.c:2760:13: note: ‘log_domain_length’ was declared here
 2760 |       gsize log_domain_length;
      |             ^~~~~~~~~~~~~~~~~
2025-04-03 14:01:20 +02:00
Marco Trevisan (Treviño)
31c9dbbc73 glib/tests/gvariant: Not try to memcpy NULL data
It's undefined behavior
2025-04-03 13:58:15 +02:00
Marco Trevisan (Treviño)
39c05b1312 gvariant-core: Add pre-condition on variant store data being non-null
We define the data not-nullable in docs, but we didn't check this
prerequisite programmatically
2025-04-03 13:58:15 +02:00
Marco Trevisan (Treviño)
28037242d5 gvariant: Do not byteswap empty GVariant values
If a value has no size, we'd end up to use g_variant_store() with a NULL
value, and this is not allowed by the API, leading to errors:

stderr:
 ../glib/gvariant-core.c:1429:9: runtime error: null pointer passed as argument
    1, which is declared to never be null
    #0 0x7f9c139ce559 in g_variant_store ../glib/gvariant-core.c:732
    #1 0x7f9c13c60b01 in g_variant_byteswap ../glib/gvariant.c:6211
    #2 0x564ae412e9b9 in test_byteswap ../glib/tests/gvariant.c:2321
    #3 0x564ae412e9b9 in test_byteswaps ../glib/tests/gvariant.c:2374
    #4 0x7f9c13bc1000 in test_case_run ../glib/gtestutils.c:3115
    #5 0x7f9c13bc1000 in g_test_run_suite_internal ../glib/gtestutils.c:3210
    #6 0x7f9c13bc0d7b in g_test_run_suite_internal ../glib/gtestutils.c:3229
    #7 0x7f9c13bc0d7b in g_test_run_suite_internal ../glib/gtestutils.c:3229
    #8 0x7f9c13bc2019 in g_test_run_suite ../glib/gtestutils.c:3310
    #9 0x7f9c13bc216f in g_test_run ../glib/gtestutils.c:2379
    #10 0x564ae410f326 in main ../glib/tests/gvariant.c:6045
2025-04-03 13:58:15 +02:00
Marco Trevisan (Treviño)
aee7b2b092 gbytes: Return early if a NULL or 0-sized GBytes is created
In case data is NULL we ended up to call memcpy with NULL parameter
which is undefined behavior (see the trace below).

So instead of having multiple null checks to do just the same, simplify
the NULL or 0-sized cases.

../glib/gbytes.c:140:7: runtime error: null pointer passed as argument 2,
  which is declared to never be null
    #0 0x7f56ea7c667e in g_bytes_new ../glib/gbytes.c:140
    #1 0x5557c3659f06 in test_null ../glib/tests/bytes.c:453
    #2 0x7f56ea9c0f70 in test_case_run ../glib/gtestutils.c:3115
    #3 0x7f56ea9c0f70 in g_test_run_suite_internal ../glib/gtestutils.c:3210
    #4 0x7f56ea9c0ceb in g_test_run_suite_internal ../glib/gtestutils.c:3229
    #5 0x7f56ea9c1f89 in g_test_run_suite ../glib/gtestutils.c:3310
    #6 0x7f56ea9c20df in g_test_run ../glib/gtestutils.c:2379
    #7 0x5557c36599d2 in main ../glib/tests/bytes.c:536
2025-04-03 13:58:15 +02:00
Marco Trevisan (Treviño)
ea52feb658 gio/tests/gdbus-export: Ensure we call all the callbacks on return
Ensure we don't do an user-after-free access, as reported by ASAN:

  ==3704==ERROR: AddressSanitizer: stack-use-after-return on address
   0x70a58f8631c0 at pc 0x000000405144 bp 0x7fffff62c7a0 sp 0x7fffff62c798
   READ of size 4 at 0x70a58f8631c0 thread T0
    #0 0x405143 in on_object_unregistered ../../GNOME/glib/gio/tests/gdbus-export.c:597
    #1 0x70a592e858d8 in call_destroy_notify_data_in_idle ../../GNOME/glib/gio/gdbusconnection.c:244
    #2 0x70a5940016a4 in g_idle_dispatch ../../GNOME/glib/glib/gmain.c:6221
    #3 0x70a59401095b in g_main_dispatch ../../GNOME/glib/glib/gmain.c:3348
    #4 0x70a59401095b in g_main_context_dispatch_unlocked ../../GNOME/glib/glib/gmain.c:4197
    #5 0x70a59401ba17 in g_main_context_iterate_unlocked ../../GNOME/glib/glib/gmain.c:4262
    #6 0x70a59401cc73 in g_main_context_iteration ../../GNOME/glib/glib/gmain.c:4327
    #7 0x405658 in test_threaded_unregistration_iteration ../../GNOME/glib/gio/tests/gdbus-export.c:1878
    #8 0x405658 in test_threaded_unregistration ../../GNOME/glib/gio/tests/gdbus-export.c:1952
    #9 0x70a5940dfb04 in test_case_run ../../GNOME/glib/glib/gtestutils.c:2988
    #10 0x70a5940dfb04 in g_test_run_suite_internal ../../GNOME/glib/glib/gtestutils.c:3090
    #11 0x70a5940df893 in g_test_run_suite_internal ../../GNOME/glib/glib/gtestutils.c:3109
    #12 0x70a5940df893 in g_test_run_suite_internal ../../GNOME/glib/glib/gtestutils.c:3109
    #13 0x70a5940e0bc9 in g_test_run_suite ../../GNOME/glib/glib/gtestutils.c:3189
    #14 0x70a5940e0d1f in g_test_run ../../GNOME/glib/glib/gtestutils.c:2275
    #15 0x40eb72 in session_bus_run ../../GNOME/glib/gio/tests/gdbus-sessionbus.c:69
    #16 0x403a2c in main ../../GNOME/glib/gio/tests/gdbus-export.c:1990
    #17 0x70a591d9f149 in __libc_start_call_main (/lib64/libc.so.6+0x28149) (BuildId: 0d710e9d9dc10c500b8119c85da75004183618e2)
    #18 0x70a591d9f20a in __libc_start_main_impl (/lib64/libc.so.6+0x2820a) (BuildId: 0d710e9d9dc10c500b8119c85da75004183618e2)
    #19 0x403b44 in _start (/tmp/_build/gio/tests/gdbus-export+0x403b44) (BuildId: f6312e919c3d94e4c49270b0dfc5c870e1ba550b)

Address 0x70a58f8631c0 is located in stack of thread T0 at offset 192 in frame
    #0 0x40525f in test_threaded_unregistration ../../GNOME/glib/gio/tests/gdbus-export.c:1936

  This frame has 7 object(s):
    [32, 40) 'local_error' (line 1835)
    [64, 72) 'unregister_thread' (line 1836)
    [96, 104) 'value' (line 1838)
    [128, 136) 'value_str' (line 1839)
    [160, 168) 'call_result' (line 1840)
    [192, 204) 'object_registration_data' (line 1834) <== Memory access at offset 192 is inside this variable
    [224, 240) 'data' (line 1833)
2025-04-03 13:58:15 +02:00
Marco Trevisan (Treviño)
6ed59a6f40 gio/tests/gdbus-connection: Fix typo 2025-04-03 13:58:15 +02:00
Marco Trevisan (Treviño)
efe215809b glib/glib-private: Mark the dynamic LSAN checks as unlikely
It's not normal to run programs with leak sanitizer enabled, so let's
mark those checks as such, in case the compiler can optimize them
2025-04-03 13:58:15 +02:00
Marco Trevisan (Treviño)
b11c121747 gcharset: Mark cached data as known leak
The charset data is never freed but it's something stored per thread
so we can safely ignore the leak
2025-04-03 13:58:15 +02:00
Marco Trevisan (Treviño)
0453908570 gthread: Mark data allocated with g_private_set_alloc0 as leaking
This is what we already ignored with valgrind and it's something that
we should always ignore since it's leaked by design.

So do explicitly mark it as such.
2025-04-03 13:57:18 +02:00
Marco Trevisan (Treviño)
a3eccd6316 gthread: Clarify when g_private_set_alloc0() suppression happens with valgrind 2025-04-03 13:57:18 +02:00
Marco Trevisan (Treviño)
0a47b69b46 girepository/parser: Clarify ownership of nodetype nodes
We may had free'd a list of items without freeing the items in there.
So now, properly steal the data instead and free everything.
2025-04-03 13:57:18 +02:00
Marco Trevisan (Treviño)
98de5367d3 girepository/compiler: Cleanup the parser error on failure 2025-04-03 13:57:18 +02:00
Marco Trevisan (Treviño)
cc070e1a7d girepository/compiler: Cleanup the parser on write failures 2025-04-03 13:57:18 +02:00
Philip Withnall
416bab52eb tests: Fix a memory leak if a callable-info test is skipped
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2025-04-03 13:57:18 +02:00
Marco Trevisan (Treviño)
7086823bb2 cancellable: Connect to cancelled signal using the ID
Avoid fetching the signal-ID by its name since we know it here
2025-04-02 21:28:03 +02:00
Michael Catanzaro
eedf75e810 Merge branch 'variant-type-docs' into 'main'
gvarianttype: Improve docs on type validation

See merge request GNOME/glib!4571
2025-04-02 16:04:25 +00:00
Emmanuele Bassi
93371e1f56 Merge branch 'dbus-name-owning-docs' into 'main'
gdbusnameowning: Convert docs to gi-docgen linking syntax

See merge request GNOME/glib!4562
2025-04-02 13:10:05 +00:00
Philip Withnall
4820b1bd79 Merge branch '3649-win32-wchar-crash' into 'main'
gwin32appinfo: Fix an incorrect size vs wide-length comparison

Closes #3649

See merge request GNOME/glib!4572
2025-04-02 11:35:12 +00:00
Philip Withnall
afb5ba1ea1 Merge branch 'doc-prgname' into 'main'
gutils: make documentation of g_set_prgname() clearer

See merge request GNOME/glib!4567
2025-04-02 10:48:53 +00:00
Integral
ead02072a4
gutils: make documentation of g_set_prgname() clearer 2025-04-02 18:33:38 +08:00
Philip Withnall
18eb38fa15
gvarianttype: Improve docs on type validation
Spotted by skrcprst.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2025-04-02 11:08:04 +01:00
Patrick Griffis
cce3001d5d threadedresolver: Cache network interface checks 2025-04-01 19:11:49 -05:00
Philip Withnall
f1a498e178 Merge branch 'protect-argv-string' into 'main'
gspawn-win32: Fix potential integer overflows in argv handling

See merge request GNOME/glib!4570
2025-04-01 16:14:35 +00:00
Philip Withnall
585ec33763
gwin32appinfo: Clarify some variable names
See the previous commit. Clarify these variable names so it’s more
obvious they contain a size in bytes rather than a length in wide-chars.

This introduces no functional changes.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Helps: #3649
2025-04-01 16:05:44 +01:00
Philip Withnall
6f9bb9b784
gwin32registrykey: Clarify that value sizes are in bytes
It can be confusing otherwise when getting string values: is the size in
bytes or wide-characters?

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Helps: #3649
2025-04-01 16:04:01 +01:00
Philip Withnall
464dd6fb6b
gwin32appinfo: Fix an incorrect size vs wide-length comparison
`value_size` is in bytes, whereas `ms_resource_prefix_len` is in wide
characters, so they cannot be compared directly. This meant that if
12 ≤ `value_size` < 24 then the call to `memcmp()` would read off the
end of `value`.

Fix it by using a wide-character and nul-aware comparison function and
operating only on wide-lengths. This is safe because
`g_win32_registry_key_get_value_w()` guarantees that string-typed return
values are nul-terminated.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Fixes: #3649
2025-04-01 15:50:00 +01:00
Philip Withnall
3d9cc10330
gspawn-win32: Fix potential integer overflows in argv handling
This can happen if a user passes a ludicrously long string to argv.

Spotted by chamalsl as #YWH-PGM9867-48.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2025-03-30 21:49:05 +01:00