[glib/th/g-ascii-strtoll-preserve-errno] glib: avoid setting wrong errno in g_ascii_strtoll() et all.
- From: Thomas Haller <thaller src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/th/g-ascii-strtoll-preserve-errno] glib: avoid setting wrong errno in g_ascii_strtoll() et all.
- Date: Mon, 4 May 2020 20:07:01 +0000 (UTC)
commit d550456cbf1b1ffaa92d76e1d35d2ae367b0996f
Author: Thomas Haller <thaller redhat com>
Date: Mon May 4 22:05:58 2020 +0200
glib: avoid setting wrong errno in g_ascii_strtoll() et all.
In CI tests of NetworkManager, it happened sporadically that
g_ascii_strtoll() for "10" would set errno to EAGAIN. The code
in NetworkManager first initializes errno to zero and does not
expect that g_ascii_strtoll() would set errno in case of success.
Since we employed a workaround (to retry) in case of EAGAIN,
the CI failures appear to be gone ([2]).
It's not clear to me how that happened, but I can only imagine that
it was due to newlocale(). So, do two things:
- ensure that we remember and restore errno while calling newlocale().
- under the assumption that newlocale might fail sporadically with
EAGAIN, retry a few times. Since we cache the returned locale for
all future invocations, it's rather important that we get this right.
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1797915
[2]
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/commit/d342fa267d59cd317cc3cc798824c70b1158ff61
glib/gstrfuncs.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
---
diff --git a/glib/gstrfuncs.c b/glib/gstrfuncs.c
index f34aca29d..29aa91c21 100644
--- a/glib/gstrfuncs.c
+++ b/glib/gstrfuncs.c
@@ -328,13 +328,26 @@ const guint16 * const g_ascii_table = ascii_table_data;
static locale_t
get_C_locale (void)
{
- static gsize initialized = FALSE;
- static locale_t C_locale = NULL;
+ static gsize initialized = 0;
+ static locale_t C_locale;
if (g_once_init_enter (&initialized))
{
- C_locale = newlocale (LC_ALL_MASK, "C", NULL);
+ int errsv = errno;
+ int try_count = 0;
+ locale_t l;
+
+again:
+ l = newlocale (LC_ALL_MASK, "C", NULL);
+ if ( l == (locale_t) 0
+ && ++try_count < 3)
+ {
+ /* creating the C locale failed. This is unexpected. Try again... */
+ goto again;
+ }
+
g_once_init_leave (&initialized, TRUE);
+ errno = errsv;
}
return C_locale;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]