Move the separate function inline using g_once_init_{enter,leave}(),
rather than g_once().
This marginally improves performance, taking 0.39s to create 10000000
UTC timezones, rather than 0.43s previously. (Who cares?)
Follow-up to !1105.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
It’s quite surprising that this wasn’t documented already. Hash tables
are unordered, and any recognisable iteration ordering is not guaranteed
and might change in future releases.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Instead only do a g_critical(). This is something that has to be fixed
one way or another, but a g_critical() is less disruptive and makes sure
that code that worked in previous GLib versions still works as bad as
before.
Fixes https://gitlab.gnome.org/GNOME/glib/issues/2039
bindfs is part of the setup process, so if it fails (as can happen if
the `fuse` kernel module has not been loaded — not much we can do about
that) then skip the test.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Add a note to the documentation of
`g_dbus_connection_signal_unsubscribe()`, `g_bus_unwatch_name()` and
`g_bus_unown_name()` warning about the need to continue iterating the
caller’s thread-default `GMainContext` until the
unsubscribe/unwatch/unown operation is complete.
See the previous few commits and #1515 for an idea of the insidious bugs
that can be caused by not iterating the `GMainContext` until
everything’s synchronised.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
When testing that signals are delivered to the correct thread, and are
delivered the correct number of times, call `EmitSignal()` on the
`gdbus-testserver` to trigger a signal emission, and listen for that.
Previously, the code listened for `NameOwnerChanged` and connected to
the bus again to trigger emission of that. The problem with that is that
other things happening on the bus (for example, an old
`gdbus-testserver` instance disconnecting) can cause `NameOwnerChanged`
signal emissions. Sometimes, the `gdbus-threading` test was failing the
`signal_count == 1` assertion due to receiving more than one
`NameOwnerChanged` emission.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1515
This is equivalent, but makes the loop exit conditions a little clearer,
since they’re actually in a `while` statement, rather than being a
`g_main_loop_quit()` call in a callback somewhere else in the file.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1515
As with the previous commit, don’t stop iterating the `context` in
`test_delivery_in_thread_func()` until the unsubscription from a signal
is complete, and hence there’s a guarantee that no callbacks are pending
in the `thread_context`.
This commit uses the `GDestroyNotify` for
`g_dbus_connection_signal_subscribe()` as a synchronisation message from
the D-Bus worker thread to the `test_delivery_in_thread_func()` thread
to notify of signal unsubscription.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1515
Previously, the code in `ensure_gdbus_testserver_up()` created a proxy
object and watched its `name-owner` to see when the
`com.example.TestService` name appeared.
This ended up subscribing to three signals (one of them for name
ownership, and two unused for properties of the proxy), and was racy. In
particular, the `name-owner` property could be set before all D-Bus
messages had been processed — it could have been derived from getting
the owner of the name, for example.
This left unprocessed messages hanging around in the `context`, but that
context was never iterated again, which essentially leaked the
references held by those messages. That included a reference to the
`GDBusConnection`.
The first part of the fix is to simplify the code to use
`g_bus_watch_name_on_connection()`, so there’s only one signal
subscription to worry about.
The second part of the fix is to use the `GDestroyNotify` callback for
the watch data to be notified of when all D-Bus traffic has been
processed and the signal unsubscription is complete. At this point, it’s
guaranteed that there are no idle callbacks pending in the
`GMainContext`, since the `GDestroyNotify` callback is the last one
invoked on the `GMainContext`.
Essentially, this commit uses the `GDestroyNotify` callback as a
synchronisation message between the D-Bus worker thread and the thread
calling `ensure_gdbus_testserver_up()`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1515
Iterate the given `context` while waiting, rather than sleeping. This
ensures that if the errant `GDBusConnection` ref is held by some pending
callback in the given `context`, it will actually be released.
Typically `context` is going to be the global default main context.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1515
This introduces no functional changes, but makes the code a little more
explicit about which connection and main context it’s operating on.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1515
`CallDestroyNotifyData` never uses that `GMainContext`, and holding a
ref to it could cause reference count cycles if the `GMainContext` is no
longer being iterated.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1515
The fix for bgo#651133 (commit 7e0f890e38) introduced a kind of weak
ref, which had to be thread-safe due to the fact that `GDBusProxy`
operates in one thread but can emit signals in another.
Since that commit, `GWeakRef` was added, which does the same thing. Drop
the custom code in favour of it; this should be functionally equivalent,
but using an RW lock rather than a basic mutex, which should reduce
contention.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
These checks used to be a precondition on test_threaded_singleton(); but
the earlier tests could leave the refcount of the shared connection in a
bad state, and this wouldn’t be caught until later.
Factor out the check, increase the iteration count to 1000 (so the check
blocks for up to 1s rather than 100ms), and call it in more places.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
https://gitlab.gnome.org/GNOME/glib/issues/1515
g_assert() can be compiled out with G_DISABLE_ASSERT, which renders the
test rather useless.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
https://gitlab.gnome.org/GNOME/glib/issues/1515
Newer versions of xdg-desktop-portal need a newer PipeWire, so use the
latest release that doesn't contain this change to avoid having
something else to build.
CI scripts are done using a shell with 'set -e' enabled, but using
'&&' means that the line won't "fail". Run the different commands
sequentially instead.
Spotted by Simon McVittie <smcv@collabora.com>
Closes: #2043
When calling `g_set_object()` for a type derived from `GObject`, GCC 9.2
was giving the following strict aliasing warning:
```
../../source/malcontent/libmalcontent-ui/user-controls.c:1001:21: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
1001 | if (g_set_object (&self->user, user))
/opt/gnome/install/include/glib-2.0/gobject/gobject.h:744:33: note: in definition of macro ‘g_set_object’
744 | (g_set_object) ((GObject **) (object_ptr), (GObject *) (new_object)) \
| ^~~~~~~~~~
```
This was due to the `(GObject **)` cast.
Pass the pointer through a union to squash this warning. We already do
some size and type checks of the dereferenced type, which should catch
casual errors. The `g_object_ref()` and `g_object_unref()` calls which
subsequently happen inside the `g_set_object()` function also do some
dynamic type checks.
Add a test.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
mtab_file_changed_id is not currently removed when finalizing, which
could potentially lead to segfaults. Let's remove the source when
finalizing to avoid this.
mtab_file_changed_id might be set on thread default context, but it is
always cleared on the global context because of usage of g_idle_add. This
can cause the emission of redundant "mounts-change" signals. This should
not cause any issues to the client application, but let's attach the idle
source to the thread-default context instead to avoid those races for sure.
The `get_mounts_timestamp()` function uses `mount_poller_time` when
`proc_mounts_watch_source` is set, but the `mount_poller_time` is not
initialized in the same time as `proc_mounts_watch_source`. This may
cause that zero, or some outdated value is returned. Let's initialize
`mount_poller_time` to prevent invalid values to be returned.
The Nautilus test suite often crashes with "GLib-FATAL-CRITICAL:
g_source_is_destroyed: assertion 'g_atomic_int_get (&source->ref_count)
> 0' failed" if it is started with "GIO_USE_VOLUME_MONITOR=unix". This
is because GUnixMountMonitor is simultaneously used from multiple
threads over GLocalFile and GVolumeMonitor APIs. Let's add guards for
proc_mounts_watch_source and mount_poller_time variables to prevent
those crashes.
Fixes: https://gitlab.gnome.org/GNOME/glib/issues/2030
There was a slight race in name ownership: a gap between calling
`RequestName` (or receiving its reply) and subscribing to `NameLost`. In
that gap, another process could request and receive the name, and this
one wouldn’t know about it.
Fix that by subscribing to `NameAcquired` and `NameLost` before calling
`RequestName`, and then unsubscribing again if the subscriptions turn
out not to be necessary (if the process can’t own the requested name).
Spotted and diagnosed by Miika Karanki.
One of the tests needs an additional iteration of the main loop in order
to free all the signal closures before it can complete its checks.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1517