GTK lost it's '+' suffix back in 2019, according to
<https://mail.gnome.org/archives/gtk-devel-list/2019-February/msg00000.html>
This commit can be re-generated with:
git grep -l GTK+ \
| grep -v -e ^NEWS -e ^glib/tests/collate.c \
| xargs sed -i 's/GTK+/GTK/g'
Most of the changes are in comments and documentation.
Many idle and timeout sources are installed as "one shot": called once
and immediately removed. While it's easy to write a simple callback that
returns G_SOURCE_REMOVE, it would also be useful to have some sort of
"visual" marker when reading the code; a way to immediately see that a
callback (which may be defined elsewhere in the code) is meant to be
invoked just once.
Includes additional unit tests by Philip Withnall.
Add SPDX license (but not copyright) headers to all files which follow a
certain pattern in their existing non-machine-readable header comment.
This commit was entirely generated using the command:
```
git ls-files glib/*.[ch] | xargs perl -0777 -pi -e 's/\n \*\n \* This library is free software; you can redistribute it and\/or\n \* modify it under the terms of the GNU Lesser General Public/\n \*\n \* SPDX-License-Identifier: LGPL-2.1-or-later\n \*\n \* This library is free software; you can redistribute it and\/or\n \* modify it under the terms of the GNU Lesser General Public/igs'
```
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #1415
It fixes a race. g_source_attach() had the following check to ensure a
loop blocked on poll() would wakeup.
if (do_wakeup && context->owner && context->owner != G_THREAD_SELF)
g_wakeup_signal (context->wakeup);
However it doesn't contemplate an implementation where poll()ing is a
non-blocking operation that will be scheduled while the thread is
released to perform other tasks. This scenario opens up several
different possibilities where the condition would fail to hold true. I
experienced two of such races.
The first race pertains to a mono-threaded application. Do keep in mind
that integrating GLib to a foreign event loop will make GLib act as a
slave in the new event loop. When you post a new work unit to execute in
the thread managed by the foreign event loop, you don't use
g_main_context_invoke(). In fact the only reason to integrate
GMainContext in a foreign event loop is to make the two of them
communicate. So from time to time, the foreign event loop will execute
callbacks that manipulate the GMainContext loop. An illustration
follows.
// in this callback we translate an event from the foreign event loop
// to an event in the GMainContext event loop (that runs in the same
// thread)
static void my_event_loop_callback(void* data)
{
GMainContext* ctx = /* ... */;
// ...
g_source_attach(source, ctx);
}
int main()
{
// ...
my_event_loop_invoke(my_event_loop_callback, data);
// ...
// this function has all mechanisms in place to run the foreign
// event loop and the hooks to call
// g_main_context_{prepare,query,check,dispatch}
my_event_loop_run();
}
In this case, you would have the following series of calls:
1. g_main_context_prepare()
2. g_main_context_query()
3. A callback to my_event_loop is registered when any fd on the set is
ready or the timeout is reached.
4. The thread is released to perform other tasks.
5. One of the tasks executed wishes to communicate with my_event_loop
and enters my_event_loop_callback.
6. g_source_attach() is called.
7. g_source_attach() detects do_wakeup=TRUE, context->owner != NULL, and
context->owner == G_THREAD_SELF so g_wakeup_signal() is skipped.
8. None of the fds on the GLib poll() set becomes ready nor the GLib
timeout expires. The my_event_loop callback that would call
g_main_context_check() is never executed. Deadlock.
A shallow analysis will fail to detect the race here. The explanation
seems to showcase a scenario that will deterministically fail with a
deadlock every time. However do keep in mind that my_event_loop_callback
could be invoked before or after g_main_context_prepare(). There is an
_event_ race here. Furthermore, some GLib libraries such as GDBus will
initialize objects from extra threads (GAsyncInitable interface) and
invoke the result on the original thread when ready (g_source_attach()
will eventually be called). Now you have scenarios closer to standard
race examples.
The other scenario where a race would manifest happens in a
multi-threaded application that has a concurrency design similar to the
actor model. No actor executes in two threads simultaneously, but it's
not guaranteed that it'll always wake-up in the same thread. It'd
perform steps 1-4 just as in the previous example, but before thread
control is returned to the pool, it'd call g_main_context_release(). Now
g_source_attach() would skip g_wakeup_signal() for a different reason:
7. g_source_attach() detects do_wakeup=TRUE, context->owner == NULL so
g_wakeup_signal() is skipped.
8. Same as before.
Certainly there are other concurrency designs where this optimization
would cause a deadlock, but all of them have origin in the same place:
the optimization assumes the poll() implementation is a blocking
operation and the thread will never be released to perform other tasks
(possibly involving GLib calls) while result is not ready. They share
not only the same problem, but also the same solution: do not make
assumptions and just call g_wakeup_signal().
This patch implements this solution by introducing the
G_MAIN_CONTEXT_FLAGS_OWNERLESS_POLLING flag. This flag will force a call
to g_wakeup_signal() and fix the race on foreign event loops. The reason
to prevent changing this option after creation is to avoid other races
that would lead to event loss. Construction is the only proper time to
set this option.
The implementation design means we do not change **any** semantics for
current working code. If you don't set the new flag, the code won't
enter in different branches and current behavior won't be affected. The
patch is small and easy to follow too.
g_source_set_name duplicates the string, and this is
showing up as one of the more prominent sources of strdups
in GTK profiles, despite all the names we use being literals.
Add a variant that avoids the overhead.
On Unix platforms, wait() and friends yield an integer that encodes
how the process exited. Confusingly, this is usually not the same as
the integer passed to exit() or returned from main(): conceptually it's
an integer encoding of this tagged union:
enum { EXITED, SIGNALLED, ... } tag;
union {
int exit_status; /* if EXITED */
struct {
int terminating_signal;
bool core_dumped;
} terminating_signal; /* if SIGNALLED */
...
} detail;
Meanwhile, on Windows, wait statuses and exit statuses are
interchangeable.
I find that it's clearer what is going on if we are consistent about
referring to the result of wait() as a "wait status", and the value
passed to exit() as an "exit status".
GSubprocess already gets this right: g_subprocess_get_status() returns
the wait status, while g_subprocess_get_exit_status() genuinely returns
the exit status. However, the GSpawn family of APIs has tended to
conflate the two.
Confusingly, g_spawn_check_exit_status() has always checked a wait
status, and it would not be correct to pass an exit status to it; so
let's deprecate it in favour of g_spawn_check_wait_status(), which
does the same thing that g_spawn_check_exit_status() always did.
Code that needs backwards-compatibility with older GLib can use:
#if !GLIB_CHECK_VERSION(2, 69, 0)
#define g_spawn_check_wait_status(x) (g_spawn_check_exit_status (x))
#endif
Signed-off-by: Simon McVittie <smcv@collabora.com>
This is basically glnx_steal_fd() from libglnx. We already had two
private implementations of it in GLib.
Signed-off-by: Simon McVittie <smcv@collabora.com>
This reverts commit c0146be3a4e0cda7a23d7fd54cc60a0bc7ba7f7a.
The revert was originally added because the original change broke
gnome-build-meta. Now that the problem has been diagnosed, the original
commit can be fixed — see the commit which follows this one.
See: !1487
The public functions exposed as static inlines currently don't have
annotations to describe when they were introduced. This means that
compiling this file:
#include <glib.h>
void foo (void)
{
g_rec_mutex_locker_new (NULL);
}
with:
gcc -c test.c \
-I/tmp/glib/include/glib-2.0 \
-I/tmp/glib/lib/x86_64-linux-gnu/glib-2.0/include \
-Werror \
-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_28 \
-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_28
will not produce any error message, despite using
`g_rec_mutex_locker_new`, a function that was introduced after 2.28.
This patch adds some annotations to all the publicly exposed static
inline functions I could find.
I could not use the existing G_AVAILABLE* macros, because they may
expand to `extern`. This would then clash with the `static` keyword and
produce:
../glib/gthread.h:397:1: error: multiple storage classes in declaration specifiers
397 | static inline GRecMutexLocker *
| ^~~~~~
So I opted for adding a new set of macros,
GLIB_AVAILABLE_STATIC_INLINE_IN_2_XY.
With this patch applied, the example from above produces the expected
warning:
test.c: In function ‘foo’:
test.c:5:3: error: ‘g_rec_mutex_locker_new’ is deprecated: Not available before 2.60 [-Werror=deprecated-declarations]
5 | g_rec_mutex_locker_new (NULL);
| ^~~~~~~~~~~~~~~~~~~~~~
In file included from /tmp/glib/include/glib-2.0/glib/gasyncqueue.h:32,
from /tmp/glib/include/glib-2.0/glib.h:32,
from test.c:1:
/tmp/glib/include/glib-2.0/glib/gthread.h:398:1: note: declared here
398 | g_rec_mutex_locker_new (GRecMutex *rec_mutex)
| ^~~~~~~~~~~~~~~~~~~~~~
This means that GLib will generate appropriate deprecation warnings if
`GLIB_VERSION_MAX_ALLOWED` has been set to target a GLib version older
than 2.58.
This allows GSource implementors to safely clear any other references to
the GSource while the GSource is still valid, unlike when doing the same
from the finalize function.
After the dispose function has run, it is valid for the reference count
of the GSource to be > 0 again to allow the case where another thread in
the mean-time got access to the GSource reference before the dispose
function was called.
This allows fixing a thread-safety issue in the GCancellable, GstBus and
various other GSource implementations.
This is like `GMutexLocker`, in that if you are able to use
`g_autoptr()`, it makes popping a `GMainContext` off the thread-default
main context stack easier when exiting a function.
A few uses of `G_GNUC_{BEGIN,END}_IGNORE_DEPRECATIONS` are needed to
avoid warnings when building apps against GLib with
`GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_64`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
These macros wrap functions which were only introduced in certain
versions of GLib. The functions are correctly marked as introduced in
those versions, but the macros aren’t, which can result in not getting
appropriate deprecation warnings if you’re using those APIs when you
have said you’re targeting older GLib versions using
`GLIB_VERSION_MAX_ALLOWED`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Closes: #1860
GTimeVal is subject to the year 2038 problem, since its `tv_sec` field
is a `glong`, which is 32 bits on 32-bit platforms.
Use `guint64` to represent microsecond-precision time since the Unix
epoch; or use `GDateTime` for full date/time representation.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1438
It’s been de-facto deprecated for a long time, due to emitting a
critical warning when used in a non-internal context. Make that official
in the documentation and with a deprecation annotation.
Split the implementation into an internal helper and an external
wrapper, so the two remaining internal uses don’t emit deprecation
warnings.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
https://gitlab.gnome.org/GNOME/glib/issues/903
It's a very common pattern to see code that looks like this in
dispose() or finalize() implementations:
if (priv->source_id > 0)
{
g_source_remove (priv->source_id);
priv->source_id = 0;
}
This API allows to accomplish the same goal with a single line:
g_clear_handle_id (&priv->source_id, (GClearHandleFunc) g_source_remove);
Thanks to Emmanuele Bassi <ebassi@gnome.org> for making the patch
generic.
https://bugzilla.gnome.org/show_bug.cgi?id=788489
All glib/*.{c,h} files have been processed, as well as gtester-report.
12 of those files are not licensed under LGPL:
gbsearcharray.h
gconstructor.h
glibintl.h
gmirroringtable.h
gscripttable.h
gtranslit-data.h
gunibreak.h
gunichartables.h
gunicomp.h
gunidecomp.h
valgrind.h
win_iconv.c
Some of them are generated files, some are licensed under a BSD-style
license and win_iconv.c is in the public domain.
Sub-directories inside glib/:
deprecated/: processed in a previous commit
glib-mirroring-tab/: already LGPLv2.1+
gnulib/: not modified, the code is copied from gnulib
libcharset/: a copy
pcre/: a copy
tests/: processed in a previous commit
https://bugzilla.gnome.org/show_bug.cgi?id=776504
Temporarily increase the ref count of a GSource to 1 while calling its
finalize() callback, so that the finalize() implementation can call
GSource methods (like g_source_set_ready_time()) without causing
critical warnings. It’s safe to call those methods at this point, as the
source has been destroyed, but nothing has been freed.
This is an indirect way of fixing a race between GCancellable and
GCancellableSource, whereby the GCancellable::cancelled callback for the
GCancellableSource is not disconnected until the GCancellableSource’s
finalize() function is called. Previously, this meant there was a window
in which the GCancellableSource’s ref count was 0, but the ::cancelled
callback was still connected, and could legitimately be called as a
result of another thread calling g_cancellable_cancel() on the
GCancellable. The callback calls g_source_set_ready_time() on the
GSource, and there’s no thread-safe way of checking whether the GSource
has been destroyed. Instead, we have to change GSource so its ref count
is only decremented to 0 inside the locked section in
g_source_unref_internal() *after* the finalize() function has been
called, and hence after the GCancellable::cancelled callback has been
disconnected. The use of g_cancellable_disconnect() ensures that the
callback disconnection is thread safe.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
https://bugzilla.gnome.org/show_bug.cgi?id=781601
- Mention G_SOURCE_CONTINUE and G_SOURCE_REMOVE in the GSourceFunc doc;
- Mention G_PARAM_READWRITE and G_PARAM_STATIC_STRINGS in the
GParamFlags doc;
- Fix "Since:" version for G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE;
- Fix typo.
https://bugzilla.gnome.org/show_bug.cgi?id=704250
Adding file descriptors to a GSource provides similar functionality to
the old g_source_add_poll() API with two main differences.
First: the list of handles is managed internally and therefore users are
prevented from randomly modifying the ->events field. This prepares us
for an epoll future where changing the event mask is a syscall.
Second: keeping the list internally allows us to check the ->revents for
events for ourselves, allowing the source to skip implementing
check/prepare. This also prepares us for the future by allowing an
implementation that doesn't need to iterate over all of the sources
every time.
https://bugzilla.gnome.org/show_bug.cgi?id=686853
Allow for NULL GSourceFuncs.check() and .prepare().
For prepare() the source will be taken not to be ready and having an
infinite timeout. For check() the source will be taken not to be ready.
https://bugzilla.gnome.org/show_bug.cgi?id=686853
This is the vtable pointer for the source which is usually held in
static storage. For our internal sources it points at a vtable which
the user should really never be modifying.
Mark it const.
https://bugzilla.gnome.org/show_bug.cgi?id=686853
Add the GLIB_AVAILABLE_IN_ALL annotation to all old functions (that
haven't already been annotated with the GLIB_AVAILABLE_IN_* macros or a
deprecation macro).
If we discover in the future that we cannot use only one macro on
Windows, it will be an easy sed patch to fix that.
https://bugzilla.gnome.org/show_bug.cgi?id=688681
Many (if not "almost all") programs that spawn other programs via
g_spawn_sync() or the like simply want to check whether or not the
child exited successfully, but doing so requires use of
platform-specific functionality and there's actually a fair amount of
boilerplate involved.
This new API will help drain a *lot* of mostly duplicated code in
GNOME, from gnome-session to gdm. And we can see that some bits even
inside GLib were doing it wrong; for example checking the exit status
on Unix, but ignoring it on Windows.
https://bugzilla.gnome.org/show_bug.cgi?id=679691
The Since tag for these was saying 2.28 but it was actually added in
2.31. It looks like all of the Since tags list stable version numbers
so this patch bumps that up to 2.32.
https://bugzilla.gnome.org/show_bug.cgi?id=679258