On some platforms, pointer-sized reads are not necessarily atomic, so we
always need to use the correct atomic access primitives.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Since we have a convenience method to add actions let's allow to remove
them just as easily. This makes resource cleanup as simple as initially
adding the entries.
Adds a helper to truncate UTF8 strings in the middle, allowing to make
them fit certain size constraints.
This function is modeled after similar functionality that has existed
since 2008 in nautilus and in eel before that.
If people do that, it clutters the place up with branches which are not
deleted-on-merge by default. Better to use their own forks.
And the people who are in a position to be able to push directly to
`origin` are not going to be reading the `CONTRIBUTING.md` file, so this
paragraph is noise to most readers anyway.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
GLib can’t grow forever, so we should really only be accepting APIs
which are useful across a variety of projects and which couldn’t easily
live in a separate library.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Point strongly towards `SECURITY.md` so we are not maintaining security
instructions in multiple places.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
It’s a bit confusing to have two files called `README`, especially given
that `README.win32.md` only contains build instructions and none of the
other overview/contribution/bug reporting information that `README.md`
contains.
It feels like these would be better organised by having one top-level
`README.md`, and pointing to the Windows build instructions from there.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This is a minor style change to better differentiate
signal name by enclosing it in single quotes.
Before:
<emit signal event on instance 0xf14e60 [GdkWaylandToplevel]>
After:
<emit signal 'event' on instance 0xf14e60 [GdkWaylandToplevel]>
- Commit f02ec2f2de added a gsignal fastpath where g_closure_invoke_va()
is directly called from g_signal_emit_valist() skipping signal_emit_unlocked_R()
altogether which it's the function used by gobject_gdb.py to detect
signal emission.
So we update gobject_gdb.py to also detect signals which use this
g_closure_invoke_va() fastpath.
- We also update the existent code to detect marshallers to also
include these:
surface_event_marshaller()
gdk_surface_event_marshallerv()
g_type_class_meta_marshal()
g_type_class_meta_marshalv()
This allow us that for signal emissions which use those marshallers
to keep showing the signal handler frame just after the
<emit signal blabla> line.
In the typical `while (g_file_enumerator_next_file ())` patterns,
there is nothing much checking whether the operation was cancelled
on the GIO side. Unless the user checks for the case, this means
local enumerators always run to completion even if cancelled.
Fix this by checking the cancellable state explicitly for local
enumerators, so there are oportunities for bailing out early if
the enumerator is going through a very large directory.
It's redundant, which leads to impossible code like:
if (child_watch_source->using_pidfd)
{
if (child_watch_source->poll.fd >= 0)
close (child_watch_source->poll.fd);
GChildWatchSource uses waitpid(), among pidfd and GetExitCodeProcess().
It thus only works for child processes which the user must ensure to
exist and not being reaped yet. Also, the user must not kill() the PID
after the child process is reaped and must not race kill() against
waitpid(). Also, the user must not call waitpid()/kill() after the child
process is reaped.
Previously, GChildWatchSource would call waitpid() already when adding
the source (g_child_watch_source_new()) and from the worker thread
(dispatch_unix_signals_unlocked()). That is racy:
- if a child watcher is attached and did not yet fire, you cannot call
kill() on the PID without racing against the PID being reaped on the
worker thread. That would then lead to ESRCH or even worse, killing
the wrong process.
- if you g_source_destroy() the source that didn't fire yet, the user
doesn't know whether the PID was reaped in the background. Any
subsequent kill()/waitpid() may fail with ESRCH/ECHILD or even address
the wrong process.
The race is most visible on Unix without pidfd support, because then the
process gets reaped on the worker thread or during g_child_watch_source_new().
But it's also with Windows and pidfd, because we would have waited for
the process in g_child_watch_check(), where other callbacks could fire
between reaping the process status and emitting the source's callback.
Fix all that by calling waitpid() right before dispatching the callback.
Note that the prepare callback only has one caller, which pre-initializes
the timeout argument to -1. That may be an implementation detail and not
publicly promised, but it wouldn't make sense to do it any other way in
the caller.
Also, note that g_unix_signal_watch_prepare() and the UNIX branch of
g_child_watch_prepare() already relied on that.
Note that the variable source_timeout is already initialized upon
definition, at the beginning of the block.
It's easy to see, that no code changes the variable between the variable
definition, and the place where it was initialized. It was thus
unnecessary.
It's not about dropping the unnecessary code (the compiler could do that
just fine too). It's that there is the other branch of the "if/else", where
the variable is also not initialized. But the other branch also requires
that the variable is in fact initialized to -1, because prepare()
callbacks are free not to explicitly set the output value. So both
branches require the variable to be initialized to -1, but only one of
them did. This poses unnecessary questions about whether anything is
wrong. Avoid that by dropping the redundant code.
- if a child watch source has "using_pidfd", it is never linked in the
unix_child_watches list. Drop that check.
- replace the deep nested if, with an early "continue" in the loop,
if we detect there is nothing to do. It makes the code easier to
read.
Let's move the difference between the win/unix implementations closer to
where the difference is. Thereby, we easier see the two implementations
side by side. Splitting it at a higher layer makes the code harder to
read.
This is just a preparation for what comes next.
commit bfbe7127d5 which did a code refactor in
gobject_gdb.py introduced a bug by failing to
return the signal name when a signal had no
'detail', this was preventing pretty printing
name for signals with no 'detail'.
When `copy_file_range()` support was added, I used the definition of
`copy_file_range()` from Linux, which uses `loff_t` to abstract the
different `off*_t` types.
`loff_t` doesn’t exist on FreeBSD, so this doesn’t compile, and was
caught in subsequent asynchronous CI.
Define `loff_t` with a fallback value if it’s not defined, which should
fix this and other uses of `loff_t` in `gfile.c` (for example, if
FreeBSD ever starts declaring `splice()`).
Fixes this CI failure: https://gitlab.gnome.org/GNOME/glib/-/jobs/2812302
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>