The addition causes the date to shift
forward into 1st of the next month, because a 0-based offset
is compared to be "more than" the days in the month instead of "more than
or equal to".
This is triggered by corner-cases where transition date is 6 days
off the end of the month and our calculations put it at N+1th day of the
month (where N is the number of days in the month). The subtraction should
be triggered to move the date back a week, putting it 6 days off the end;
for example, October 25 for CET DST transition; but due to incorrect comparison
the date isn't shifted back, we add 31 days to October 1st and end up
at November 1st).
Fixes issue #2215.
This reverts commit 851241f19a.
That commit avoids a performance regression but introduces a behavior regression:
changes to /etc/localtime have no effect for the remaining of the application's
runtime.
With the optimization introduced by the previous commit, we can pass NULL to
g_time_zone_new() repeatedly with no performance drawback, so we no longer have
to workaround this case.
Fixes: #2224
We cache GTimeZone instances to avoid expensive construction when the
same id is requested again.
However, if the NULL id is passed to g_time_zone_new(), we always
construct a new instance for the default/fallback timezone.
With the recent introduction of some heavy calculations[1], repeated
instance construction in such cases has visible performance impact in
nautilus list view and other such GtkTreeView consumers.
To avoid this, cache reference to a constructed default timezone and
use it the next time g_time_zone_new() is called with NULL argument,
as long as the default identifier doesn't change. We already did the
same for the local timezone[2].
Fixes: https://gitlab.gnome.org/GNOME/glib/-/issues/2204
Based on idea proposed by Sebastian Keller <skeller@gnome.org>.
[1] 25d950b61f
[2] 551e83662d
The win32 implementation of `g_getenv()` uses GSlice (from within
GQuark), which results in a deadlock when examining the `G_SLICE`
environment variable.
Fix that by inlining a basic implementation of `g_getenv()` at that call
site.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2225
There are various places glib uses __typeof__ for type safety, but
that's a GNUC extension. C++11 has standard decltype() that does a
similar job, at least for cases we care about.
This avoids C++ code to always have to cast return value of
g_object_ref() which was causing type kind of error:
error: invalid conversion from ‘gpointer’ {aka ‘void*’} to
‘GstElementFactory*’ {aka ‘_GstElementFactory*’} [-fpermissive]
g_has_typeof macro is wrongly in the public g_ namespace, internaly
symbols are usually in the glib_ namespace. This will also allow to
define glib_typeof differently on non-GNUC compilers (e.g. c++11
decltype).
glib/gtestutils.h:134:96: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘GFileError’
134 | if (!err || (err)->domain != dom || (err)->code != c) \
| ^~
glib/tests/fileutils.c:1072:15: note: in expansion of macro ‘g_assert_error’
1072 | g_assert_error (error, G_FILE_ERROR, tests[i].expected_error);
| ^~~~~~~~~~~~~~
glib/tests/array-test.c: In function ‘array_remove_index’:
glib/tests/array-test.c:388:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
388 | for (i = 0; i < garray->len; i++)
| ^
glib/tests/array-test.c: In function ‘array_remove_index_fast’:
glib/tests/array-test.c:425:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
425 | for (i = 0; i < garray->len; i++)
| ^
glib/tests/array-test.c: In function ‘array_remove_range’:
glib/tests/array-test.c:462:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
462 | for (i = 0; i < garray->len; i++)
| ^
glib/tests/array-test.c: In function ‘array_sort’:
glib/tests/array-test.c:604:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
604 | for (i = 0; i < garray->len; i++)
| ^
glib/tests/array-test.c: In function ‘array_sort_with_data’:
glib/tests/array-test.c:636:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
636 | for (i = 0; i < garray->len; i++)
| ^
glib/tests/array-test.c: In function ‘byte_array_sort’:
glib/tests/array-test.c:1876:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
1876 | for (i = 0; i < gbarray->len; i++)
| ^
glib/tests/array-test.c: In function ‘byte_array_sort_with_data’:
glib/tests/array-test.c:1904:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
1904 | for (i = 0; i < gbarray->len; i++)
| ^
These slightly improve the tests but, more importantly, squash a
scan-build warning about assigning to a variable which is never
subsequently used:
```
../../../glib/tests/keyfile.c:1150:3: warning: Value stored to 'value' is never read
value = g_key_file_get_string (keyfile, "a", "key=", &error);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../../glib/tests/keyfile.c:1159:3: warning: Value stored to 'value' is never read
value = g_key_file_get_string (keyfile, "a", "key[", &error);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../../glib/tests/keyfile.c:1176:3: warning: Value stored to 'value' is never read
value = g_key_file_get_string (keyfile, "a", " key", &error);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 warnings generated.
```
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This should silence the following warning:
```
../../../glib/tests/mutex.c:206:5: warning: 1st function call argument is an uninitialized value
g_thread_join (threads[i]);
^~~~~~~~~~~~~~~~~~~~~~~~~~
```
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This should avoid the warning:
```
../../../glib/tests/mainloop.c:119:3: warning: Value stored to 'id' is never read
id = g_source_attach (source, ctx);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This introduces no functional changes, but should squash a warning from
`scan-build`:
```
../../../glib/ghash.c:575:3: warning: Value stored to 'small' is never read
small = FALSE;
```
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
GLib uses NULL-terminated string arrays (GStrv) in a number of places, however
these are quite hard to construct in C when the number of elements is not known
in advance. GStrvBuilder wraps GPtrArray to make these easy to create with
type safety and does the memory management for you.
This introduces no functional changes, but makes the refcount handling a
little easier to follow by no longer splitting a ref/unref pair across
three callbacks. Now, the ref/unref pairs are all within function-local
scopes.
Coverity CID: #1430783
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
commit 916297be79 added a hash table
to provide constant time lookups of signal handlers.
Unfortunately, that commit neglected to remove handlers from
g_signal_connect_object calls from the hash table that are
disconnected implicitly when the associated object goes away.
This commit addresses that bug by changing the closure invalidate
handler associated with the signal connection to properly remove the
handler from the hash table.
When unref'ing child sources, the lock is already held. But instead of
passing TRUE to g_source_unref_internal it currently passes whether the
lock was already held outside of the current invocation. Just pass TRUE
to fix this possible issue.
By default, when using g_subprocess_launcher_take_fd() to pass an
FD to a child, the GSubprocessLauncher object also takes ownership
of the FD in the parent, and closes it during finalize(). This is
a reasonable assumption in the majority of the cases, but sometimes
it isn't a good idea.
An example is when creating a GSubprocessLauncher in JavaScript:
here, the destruction process is managed by the Garbage Collector,
which means that those sockets will remain opened for some time
after all the references to the object has been droped. This means
that it could be not possible to detect when the child has closed
that same FD, because in order to make that work, both FDs
instances (the one in the parent and the one in the children) must
be closed. This can be a problem in, as an example, a process that
launches a child that communicates with Wayland using an specific
socket (like when using the new API MetaWaylandClient).
Of course, it isn't a valid solution to manually call close() in
the parent process just after the call to spawn(), because the FD
number could be reused in the time between it is manually closed,
and when the object is destroyed and closes again that FD. If that
happens, it will close an incorrect FD.
One solution could be to call run_dispose() from Javascript on the
GSubprocessLauncher object, to force freeing the resources.
Unfortunately, the current code frees them in the finalize()
method, not in dispose() (this is fixed in !1670 (merged) ) but it
isn't a very elegant solution.
This proposal adds a new method, g_subprocess_launcher_close(),
that allows to close the FDs passed to the child. To avoid problems,
after closing an FD with this method, no more spawns are allowed.
Fix: https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1677
It’s landed in kernel 5.9: http://lkml.iu.edu/hypermail/linux/kernel/2008.0/02649.html
Note, this is untested because I currently don’t have kernel 5.9. We can
fix anything up if it breaks once the new syscall is wrapped in glibc.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Originally, GSocketClient returned whatever error occured last. Turns
out this doesn't work well in practice. Consider the following case:
DNS returns an IPv4 and IPv6 address. First we'll connect() to the
IPv4 address, and say that succeeds, but TLS is enabled and the TLS
handshake fails. Then we try the IPv6 address and receive ENETUNREACH
because IPv6 isn't supported. We wind up returning NETWORK_UNREACHABLE
even though the address can be pinged and a TLS error would be more
appropriate. So instead, we now try to return the error corresponding
to the latest attempted GSocketClientEvent in the connection process.
TLS errors take precedence over proxy errors, which take precedence
over connect() errors, which take precedence over DNS errors.
In writing this commit, I made several mistakes that were caught by
proxy-test.c, which tests using GSocketClient to make a proxy
connection. So although adding a new test to ensure we get the
best-possible error would be awkward, at least we have some test
coverage for the code that helped avoid introducing bugs.
Fixes#2211
We should never return unknown errors to the application. This would be
a glib bug.
I don't think it's currently possible to hit these cases, so asserts
should be OK. For this to happen, either (a) a GSocketAddressEnumerator
would have to return NULL on its first enumeration, without returning an
error, or (b) there would have to be a bug in our GSocketClient logic.
Either way, if such a bug were to exist, it would be better to surface
it rather than hide it.
These changes are actually going to be effectively undone in a
subsequent commit, as I'm refactoring the error handling, but the commit
history is a bit nicer with two separate commits, so let's go with two.