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
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
`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
The AI_ADDRCONFIG flag filters out addresses for invalid interfaces. This causes it to resolve nothing when only having loopback interfaces.
So we can detect if you only have loopback interfaces, request all addresses, and filter out non-loopback results.
Closes#3641
Rather than creating files in the current directory. This is a bit
neater, and avoids races between parallel invocations of the unit tests
if the file names aren’t guaranteed to be unique (e.g. by using
`g_mkstemp()`).
Add `G_TEST_OPTION_ISOLATE_DIRS` too, to make sure we use a unique
subdirectory of `g_get_tmp_dir()`. This means that paths like
`g_get_tmp_dir() / some-file` are guaranteed to be race-free even if the
filename is not unique, because the test tmp dir now is.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
In the `g-file-info-filesystem-readonly` test.
This doesn’t introduce any functional changes, but makes the code a
little easier to read (because the parts of the path are now in
hierarchical order) and makes it a bit clearer that we’re building a
path rather than an arbitrary string.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
It’s not entirely clear from the documentation, but `g_mkstemp()` (and
`g_mkdtemp()`) operate in the current directory, rather than the system
temporary directory.
This meant these tests were all writing files to the build directory.
This is messy, though thankfully not a correctness issue or a race
because `g_mkstemp()` guarantees to return a unique file for each
caller.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Previously, we were getting the string representation. However, this
representation gets escaped, which breaks non-ascii characters, because we
were counting on the path being the original path, which was not true in
these cases.
Retrieve it rather as the byte string which it is.
Fixes#3636.
Its symbol interposition works differently to that of Linux, so our
approach using `dlsym(RTLD_NEXT)` to inject syscalls (and still allow
chaining up to the version from libc) doesn’t work on macOS.
See https://gitlab.gnome.org/GNOME/glib/-/jobs/4861349 for an example
failure.
It would be lovely to have these tests working on macOS, but I am not a
macOS developer, and have spent enough time fixing this leak (#1250)
already. It can wait for follow-up work.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Helps: #1250
The algorithm that `g_socket_listener_add_any_inet_port()` and
`g_socket_listener_add_inet_port()` use to try to connect to IPv4 and/or
IPv6 ports are a bit complex (especially when port allocation has to
happen in the former method). So far they’ve not really been unit
tested, which is unfortunate, and has left latent bugs.
Add some unit tests for both methods, by providing mock `socket()` (and
friends) functions to override those from libc, and using those to cause
specific syscalls to fail according to the test’s needs.
These tests demonstrate the fix for #1250 works, as the tests can be run
under memcheck and show no memory leaks. They’ve revealed a follow-up
issue, though — `g_socket_listener_add_any_inet_port()` doesn’t try a
fallback IPv4-only socket if it tries an IPv6 socket and that socket
accepts IPv4 but then fails to `listen()`. I’ve filed issue #3604 for
that.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Helps: #1250
Apparently it’s possible for `netlink/netlink.h` to be available on
Linux, when we expected it to only be available on FreeBSD, but for
`netlink/netlink_route.h` to not exist. So add a check for the latter.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Fixes: #3630
Otherwise it looks a bit like calls to `delay()` and `apply()` need to
be paired, like calls to `g_object_freeze_notify()` and
`g_object_thaw_notify()`.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Since the docs are saying what type a key must be in the schema to be
able to call that method, it makes sense to give the type in the same
format used in the schema, i.e. a GVariant type string.
Also link to the `GVariantType` documentation so the user can read up on
it further if needed.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
The array was declared one byte too short to contain the trailing nul
byte for the string literal. Spotted by gcc 15.
Fix it by allowing the compiler to work out the array length.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
GUnixFDList actually comes *after* the GDBusMethodInvocation, but this
was mistakenly putting it first.
Signed-off-by: Ryan Gonzalez <ryan.gonzalez@collabora.com>
Three of the four GApplicationCommandLine examples contained this line:
g_application_set_inactivity_timeout (app, 10000);
It is not explained (which could be confusing for readers trying to
understand the examplese), or necessary. Worse, it causes two of the
examples to pause for ten seconds if they are invoked with no command-line
arguments, which makes them seem broken (and would presumably be reported
as a bug in any real application).
So, remove these calls.
Fixes#3615
During "as-installed" testing, we should search the GIR_DIR for GIR XML,
instead of hard-coding that it is `${prefix}/share/gir-1.0`. This is
not the case on at least Debian, in order to make it possible to
install more than one architecture's flavour of `GLib-2.0.gir`,
which contains some architecture-specific `#define`s.
Also search GOBJECT_INTROSPECTION_DATADIR/GIR_SUFFIX (in practice
something like `/usr/share/gir-1.0` in all cases) to accommodate
distributions like Debian that move the architecture-independent
majority of GIR XML into /usr/share to avoid duplication, leaving
only the architecture-specific minority of files like `GLib-2.0.gir`
in the GIR_DIR.
Signed-off-by: Simon McVittie <smcv@collabora.com>
It is easy to overlook that unreffing a GVolumeMonitor doesn't
disconnect signal handlers, this can lead to segfaults from dangling
user data pointers.
The documentation for g_spawn_async_with_pipes_and_fds() states:
> If an error occurs, child_pid, stdin_pipe_out, stdout_pipe_out, and
> stderr_pipe_out will not be filled with valid values.
Before 2dc3a6f0c8, the `child_pid`
argument was `self->pid`, and GObject zero-initializes structs. So
the pid field was properly initialized to zero.
After 2dc3a6f0c8, however, the out
variable is now declared inside initable_init(), and it's unitialized.
So if g_spawn_async_with_pipes_and_fds() errors out, `pid` will have
trash value in it, and the following assertion will fail:
```
g_assert (success == (pid != 0));
```
Fix that by initializing the `pid` variable to zero. Add a test to
exercise the fail code path, and prevent errors like this in the
future.
The process PID is initialized by the initable vfunc, while
g_subprocess_exited sets it again, when we're protecting it via a lock.
The status is set when the process exits instead, again while locking.
This makes the thread sanitizer unhappy (even if it shouldn't really be
a race for the PID init case), but still locking during initialization is
not a bad thing to do.
At the same time g_subprocess_wait() and friends were using the pid and status
values without any protection, so let's ensure this is not the case anymore.
WARNING: ThreadSanitizer: data race (pid=8213)
Write of size 4 at 0x7b200000084c by thread T1:
#0 g_subprocess_exited ../gio/gsubprocess.c:284
#1 g_child_watch_dispatch ../glib/gmain.c:5963
#2 g_main_dispatch ../glib/gmain.c:3373
#3 g_main_context_dispatch_unlocked ../glib/gmain.c:4224
#4 g_main_context_iterate_unlocked ../glib/gmain.c:4289
#5 g_main_context_iteration ../glib/gmain.c:4354
#6 glib_worker_main ../glib/gmain.c:6553
#7 g_thread_proxy ../glib/gthread.c:892
Previous read of size 4 at 0x7b200000084c by main thread:
#0 g_subprocess_wait ../gio/gsubprocess.c:908
#1 g_subprocess_wait_check ../gio/gsubprocess.c:939
#2 end_element ../gio/glib-compile-resources.c:342
#3 emit_end_element ../glib/gmarkup.c:1045
#4 g_markup_parse_context_parse ../glib/gmarkup.c:1603
#5 parse_resource_file ../gio/glib-compile-resources.c:578
#6 main ../gio/glib-compile-resources.c:967
Location is heap block of size 120 at 0x7b2000000800 allocated by main
thread:
#0 calloc <null>
#1 g_malloc0 ../glib/gmem.c:133
#2 g_type_create_instance ../gobject/gtype.c:1933
#3 g_object_new_internal ../gobject/gobject.c:2621
#4 g_object_new_valist ../gobject/gobject.c:2960
#5 g_initable_new_valist ../gio/ginitable.c:245
#6 g_initable_new ../gio/ginitable.c:163
#7 g_subprocess_newv ../gio/gsubprocess.c:619
#8 g_subprocess_new ../gio/gsubprocess.c:590
#9 end_element ../gio/glib-compile-resources.c:334
#10 emit_end_element ../glib/gmarkup.c:1045
#11 g_markup_parse_context_parse ../glib/gmarkup.c:1603
#12 parse_resource_file ../gio/glib-compile-resources.c:578
#13 main ../gio/glib-compile-resources.c:967
Thread T1 'gmain' (tid=8228, running) created by main thread at:
#0 pthread_create <null>
#1 g_system_thread_new ../glib/gthread-posix.c:762
#2 g_thread_new_internal ../glib/gthread.c:996
#3 g_thread_new ../glib/gthread.c:949
#4 g_get_worker_context ../glib/gmain.c:6580
#5 initable_init ../gio/gsubprocess.c:443
#6 g_initable_init ../gio/ginitable.c:129
#7 g_initable_new_valist ../gio/ginitable.c:249
#8 g_initable_new ../gio/ginitable.c:163
#9 g_subprocess_newv ../gio/gsubprocess.c:619
#10 g_subprocess_new ../gio/gsubprocess.c:590
#11 end_element ../gio/glib-compile-resources.c:334
#12 emit_end_element ../glib/gmarkup.c:1045
#13 g_markup_parse_context_parse ../glib/gmarkup.c:1603
#14 parse_resource_file ../gio/glib-compile-resources.c:578
#15 main ../gio/glib-compile-resources.c:967
SUMMARY: ThreadSanitizer: data race ../gio/gsubprocess.c:284 in
g_subprocess_exited
======================================
WARNING: ThreadSanitizer: data race (pid=15959)
Read of size 4 at 0x7b200000084c by main thread:
#0 g_subprocess_wait ../gio/gsubprocess.c:913
#1 g_subprocess_wait_check ../gio/gsubprocess.c:944
#2 test_cat_utf8 ../gio/tests/gsubprocess.c:489
#3 test_case_run ../glib/gtestutils.c:3115
#4 g_test_run_suite_internal ../glib/gtestutils.c:3210
#5 g_test_run_suite_internal ../glib/gtestutils.c:3229
#6 g_test_run_suite ../glib/gtestutils.c:3310
#7 g_test_run ../glib/gtestutils.c:2379
#8 main ../gio/tests/gsubprocess.c:2266
Previous write of size 4 at 0x7b200000084c by thread T1:
#0 g_subprocess_exited ../gio/gsubprocess.c:284
#1 g_child_watch_dispatch ../glib/gmain.c:5963
#2 g_main_dispatch ../glib/gmain.c:3373
#3 g_main_context_dispatch_unlocked ../glib/gmain.c:4224
#4 g_main_context_iterate_unlocked ../glib/gmain.c:4289
#5 g_main_context_iteration ../glib/gmain.c:4354
#6 glib_worker_main ../glib/gmain.c:6553
#7 g_thread_proxy ../glib/gthread.c:892