In preparation for deprecating the old APIs. This shouldn’t functionally
affect the tests.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1931
These are alternatives to the existing `time_t`-based APIs, which will
soon be deprecated due to `time_t` only being Y2038-safe on 64-bit
systems.
The new APIs take a GDateTime instead.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1931
When targeting mingw on architectures other than x86, the earlier cases
don't apply, and the final fallback, raise(SIGTRAP) isn't usable there.
GCC and Clang both support __builtin_trap(), so in case we have no
other alternatives, and are on windows (where raise() isn't available),
we can resort to this.
When timeout grater than 0 in g_poll function, the WaitForMultipleObjects
call will wait for all the threads to return, but when only one thread
got an event the others will sleep until the timeout elapses, and causes
a stall. Triggering the stop event in g_poll in this case is useless as
it is triggered when all the threads where already signaled or timed-out.
Closes: https://gitlab.gnome.org/GNOME/glib/issues/2107
The g_once() function exists to call a callback function exactly once,
and to block multiple contending threads on its completion, then to
return its return value to all of them (so they all see the same value).
The full implementation of g_once() (in g_once_impl()) uses a mutex and
condition variable to achieve this, and is needed in the contended case,
where multiple threads need to be blocked on completion of the callback.
However, most of the times that g_once() is called, the callback will
already have been called, and it just needs to establish that it has
been called and to return the stored return value.
Previously, a fast path was used if we knew that memory barriers were
not needed on the current architecture to safely access two dependent
global variables in the presence of multi-threaded access. This is true
of all sequentially consistent architectures.
Checking whether we could use this fast path (if
`G_ATOMIC_OP_MEMORY_BARRIER_NEEDED` was *not* defined) was a bit of a
pain, though, as it required GLib to know the memory consistency model
of every architecture. This kind of knowledge is traditionally a
compiler’s domain.
So, simplify the fast path by using the compiler-provided atomic
intrinsics, and acquire-release memory consistency semantics, if they
are available. If they’re not available, fall back to always locking as
before.
We definitely need to use `__ATOMIC_ACQUIRE` in the macro implementation
of g_once(). We don’t actually need to make the `__ATOMIC_RELEASE`
changes in `gthread.c` though, since locking and unlocking a mutex
guarantees to insert a full compiler and hardware memory barrier
(enforcing sequential consistency). So the `__ATOMIC_RELEASE` changes
are only in there to make it obvious what stores are logically meant to
match up with the `__ATOMIC_ACQUIRE` loads in `gthread.h`.
Notably, only the second store (and the first load) has to be atomic.
i.e. When storing `once->retval` and `once->status`, the first store is
normal and the second is atomic. This is because the writes have a
happens-before relationship, and all (atomic or non-atomic) writes
which happen-before an atomic store/release are visible in the thread
doing an atomic load/acquire on the same atomic variable, once that load
is complete.
References:
* https://preshing.com/20120913/acquire-and-release-semantics/
* https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc/_005f_005fatomic-Builtins.html
* https://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync
* https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1323
There were multi-threaded tests for g_once_init_{enter,leave}(), but not
for g_once(). Add one which tests multi-threaded contention for entering
and retrieving the value of the `GOnce`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1323
It’s not expected that bindings will use `GThread` over their own
threading APIs (in fact that would generally be a bad idea, since
threads benefit from being integrated into language control flow
structures), but it can’t hurt to have the annotations right for
documentation purposes if nothing else.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #602
Unify the creation of GPtrArray.
Maybe we will add yet another constructor for creating %NULL terminated
arrays. Unify the constructors by adding an internal helper method.
The alternative instead of adding a ptr_array_new() helper, would be to
let everybody call g_ptr_array_full(). For no strong reasons, choose
this approach because the compiler is more eager to inline the static
helper as it would inlining g_ptr_array_full().
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 seems to have existed since the code was written and I can’t see
a need for it.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #2106
g_ptr_array_extend_and_steal() leaves the GPtrArray in an invalid state,
so if you would try to append another pointer, it leads to a crash.
Also adjust the test case so that it would result in the crash (without
the fix).
Fixes: 0675703af08d ('Adding g_ptr_array_extend_and_steal() function to glib/garray.c')
With a trivial file that just includes glib.h:
#include <glib.h>
Compiled with:
gcc -c test.c \
-I /tmp/glib/include/glib-2.0/ \
-I /tmp/glib/lib/x86_64-linux-gnu/glib-2.0/include \
-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_28 \
-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_28 \
-fmax-errors=1 \
-Werror
We get:
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: In function ‘g_rec_mutex_locker_new’:
/tmp/glib/include/glib-2.0/glib/gthread.h:396:3: error: ‘g_rec_mutex_lock’ is deprecated: Not available before 2.32 [-Werror=deprecated-declarations]
396 | g_rec_mutex_lock (rec_mutex);
| ^~~~~~~~~~~~~~~~
/tmp/glib/include/glib-2.0/glib/gthread.h:196:17: note: declared here
196 | void g_rec_mutex_lock (GRecMutex *rec_mutex);
| ^~~~~~~~~~~~~~~~
compilation terminated due to -fmax-errors=1.
The problem is that the code in the static inline functions uses
g_rec_mutex_lock, introduced after 2.28. This code is compiled
regardless of if it's actually used or not.
Suppress the warning by using G_GNUC_BEGIN_IGNORE_DEPRECATIONS /
G_GNUC_END_IGNORE_DEPRECATIONS. There are precedents for doing that,
for example g_main_context_pusher_new in gmain.h.
Tested by building with all variations of GLIB_VERSION_MIN_REQUIRED /
GLIB_VERSION_MAX_ALLOWED:
for i in $(seq 26 2 64); do
gcc -c test.c \
-I/tmp/glib/include/glib-2.0 \
-I/tmp/glib/lib/x86_64-linux-gnu/glib-2.0/include \
-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_$i \
-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_$i \
-fmax-errors=1 \
-Werror
done
Fixes: #2094
Otherwise the code ends up calling `gettext ("")`, which returns the
current translation’s header. The caller should really have provided a
NULL, parameter string, but the empty string is clear enough.
See
https://gitlab.freedesktop.org/accountsservice/accountsservice/-/merge_requests/56.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
When g_variant_get_child() is called on a variant which has not been
serialized, it serializes it which includes a call to
g_variant_release_children() and therefore means that any children
previously retrieved from the variant are no longer valid (unless
another reference is held on them) and consequently values borrowed from
those children are no longer safe to access. Add a note to the
g_variant_get_child_value() documentation to explain this.
Alternatively, we could say that after the child is freed, values
borrowed from it are no longer valid. But we already have an
implementation which hasn't changed in years which lets them stay valid
if the variant was serialized before the first
g_variant_get_child_value() call.
Here's a demonstration of the memory error:
static const char *get_first_child (GVariant *v) {
g_autoptr(GVariant) child_v = g_variant_get_child_value (v, 0);
return g_variant_get_string (child_v, NULL);
}
int main(int argc, char **argv) {
g_autoptr(GVariant) v = g_variant_new("(@ss)", g_variant_new_string ("hello"), "world");
const char *child1 = get_first_child (v);
const char *child2;
g_variant_get_child (v, 1, "&s", &child2);
printf ("%s\n", child1); // this is a memory error
return 0;
}
The local change from af0e0cb9950569828 in glib ended upstreamed
as 7359c5fd9f312cddd62146896558d8c9bd2bd4cf in valgrind, with
a few minor adjustments requested from there.
Sync this local modification to what ended up upstreamed, to avoid
any doubt regarding it for future syncs of the whole header.
The gnulib math code uses __builtin_isnanf and __builtin_isnanl
within the __GNUC__ >= 4 ifdef, and clang doesn't provide those
builtins, only the one without a suffix. Make the meson check
match the code it controls, using the exactly right builtins.
Set REPLACE_ISNAN to 1 if either of the have_isnan* functions failed,
this matches how gnulib's m4 routines does it (in gnulib/m4/isnan.m4).
This fixes the isnan functions in the gnulib math header replacement
work on Clang.
Many locales have no concept of AM/PM notation, and it’s confusing to
them. It’s an Anglo-centric concept which doesn’t belong in the API at
this level — instead, programs should use more generic format specifiers
which leave the details of how to format a date/time to the locale.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #2082
Meson 0.54.0 added a new method meson.override_dependency() that must be
used to ensure dependency consistency. This patch ensures a project that
depends on glib will never link to a mix of system and subproject
libraries. It would happen in such cases:
The system has glib 2.40 installed, and a project does:
dependency('glib-2.0', version: '>=2.60',
fallback: ['glib', 'glib_dep'])
dependency('gobject-2.0')
The first call will configure glib subproject because the system libglib
is too old, but the 2nd call will return system libgobject.
By overriding 'gobject-2.0' dependency while configuring glib subproject
during the first call, meson knows that on the 2nd call it must return
the subproject dependency instead of system dependency.
This also has the nice side effect that with Meson >0.54.0 an
application depending on glib can declare the fallback without knowing
the dependency variable name: dependency('glib-2.0', fallback: 'glib').
"\t" is not escaped by g_markup_escape_text(), as per its documentation:
"Note that this function doesn't protect whitespace and line endings
from being processed according to the XML rules for normalization of
line endings and attribute values."
The relevant portion of the XML specification
https://www.w3.org/TR/xml/#AVNormalize
"For a character reference, append the referenced character to the
normalized value."
"For a white space character (#x20, #xD, #xA, #x9), append a space
character (#x20) to the normalized value."
So the unescape code in GMarkup does the right thing as can be verified
by the added valid-17.* data files for the markup-parse unit test.
(Note that the valid-13.* data files already tested a plain tab
character in an attribute value, among other white space characters).
Note that the libxml2's xmlSetProp() function escapes "\t" into the
character reference "	".
See https://gitlab.gnome.org/GNOME/glib/-/issues/2080
Update our copy of valgrind.h from the Valgrind 3.15 release tarball,
and then re-apply our downstream change af0e0cb9950569828. No other
changes made.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
malloc() was given too small value (size of pointer,
rather than struct it points to), and subsequent call
getpwnam_r() wrote past the end of allocated block - easily
seen with valgrind.
Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com>