mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-27 14:36:16 +01:00
Merge branch 'futex-errno-kersplato' into 'main'
glib: reset errno to 0 when futex() returns EAGAIN Closes #3034 See merge request GNOME/glib!3473
This commit is contained in:
commit
0990106501
@ -54,6 +54,12 @@ struct _GRealThread
|
||||
/* Wrapper macro to call `futex_time64` and/or `futex` with simple
|
||||
* parameters and without returning the return value.
|
||||
*
|
||||
* We expect futex to sometimes return EAGAIN due to the race
|
||||
* between the caller checking the current value and deciding to
|
||||
* do the futex op. To avoid splattering errno on success, we
|
||||
* restore the original errno if EAGAIN is seen. See also:
|
||||
* https://gitlab.gnome.org/GNOME/glib/-/issues/3034
|
||||
*
|
||||
* If the `futex_time64` syscall does not exist (`ENOSYS`), we retry again
|
||||
* with the normal `futex` syscall. This can happen if newer kernel headers
|
||||
* are used than the kernel that is actually running.
|
||||
@ -70,23 +76,37 @@ struct _GRealThread
|
||||
if (res < 0 && errno == ENOSYS) \
|
||||
{ \
|
||||
errno = saved_errno; \
|
||||
syscall (__NR_futex, uaddr, (gsize) futex_op, __VA_ARGS__); \
|
||||
res = syscall (__NR_futex, uaddr, (gsize) futex_op, __VA_ARGS__); \
|
||||
} \
|
||||
if (res < 0 && errno == EAGAIN) \
|
||||
{ \
|
||||
errno = saved_errno; \
|
||||
} \
|
||||
} \
|
||||
G_STMT_END
|
||||
#elif defined(__NR_futex_time64)
|
||||
#define g_futex_simple(uaddr, futex_op, ...) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
syscall (__NR_futex_time64, uaddr, (gsize) futex_op, __VA_ARGS__); \
|
||||
} \
|
||||
#define g_futex_simple(uaddr, futex_op, ...) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
int saved_errno = errno; \
|
||||
int res = syscall (__NR_futex_time64, uaddr, (gsize) futex_op, __VA_ARGS__); \
|
||||
if (res < 0 && errno == EAGAIN) \
|
||||
{ \
|
||||
errno = saved_errno; \
|
||||
} \
|
||||
} \
|
||||
G_STMT_END
|
||||
#elif defined(__NR_futex)
|
||||
#define g_futex_simple(uaddr, futex_op, ...) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
syscall (__NR_futex, uaddr, (gsize) futex_op, __VA_ARGS__); \
|
||||
} \
|
||||
#define g_futex_simple(uaddr, futex_op, ...) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
int saved_errno = errno; \
|
||||
int res = syscall (__NR_futex, uaddr, (gsize) futex_op, __VA_ARGS__); \
|
||||
if (res < 0 && errno == EAGAIN) \
|
||||
{ \
|
||||
errno = saved_errno; \
|
||||
} \
|
||||
} \
|
||||
G_STMT_END
|
||||
#else /* !defined(__NR_futex) && !defined(__NR_futex_time64) */
|
||||
#error "Neither __NR_futex nor __NR_futex_time64 are defined but were found by meson"
|
||||
|
@ -159,6 +159,63 @@ test_mutex5 (void)
|
||||
g_assert (owners[i] == NULL);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
test_mutex_errno_func (gpointer data)
|
||||
{
|
||||
GMutex *m = data;
|
||||
|
||||
g_test_summary ("Validates that errno is not touched upon return");
|
||||
g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3034");
|
||||
|
||||
for (unsigned int i = 0; i < 1000; i++)
|
||||
{
|
||||
errno = 0;
|
||||
g_mutex_lock (m);
|
||||
g_assert_cmpint (errno, ==, 0);
|
||||
|
||||
g_thread_yield ();
|
||||
|
||||
errno = 0;
|
||||
g_mutex_unlock (m);
|
||||
g_assert_cmpint (errno, ==, 0);
|
||||
|
||||
errno = 0;
|
||||
if (g_mutex_trylock (m))
|
||||
{
|
||||
g_assert_cmpint (errno, ==, 0);
|
||||
|
||||
g_thread_yield ();
|
||||
|
||||
errno = 0;
|
||||
g_mutex_unlock (m);
|
||||
g_assert_cmpint (errno, ==, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
test_mutex_errno (void)
|
||||
{
|
||||
gsize i;
|
||||
GThread *threads[THREADS];
|
||||
GMutex m;
|
||||
|
||||
g_mutex_init (&m);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (threads); i++)
|
||||
{
|
||||
threads[i] = g_thread_new ("test_mutex_errno",
|
||||
test_mutex_errno_func, &m);
|
||||
}
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (threads); i++)
|
||||
{
|
||||
g_thread_join (threads[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static gint count_to = 0;
|
||||
|
||||
static gboolean
|
||||
@ -226,6 +283,7 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/thread/mutex3", test_mutex3);
|
||||
g_test_add_func ("/thread/mutex4", test_mutex4);
|
||||
g_test_add_func ("/thread/mutex5", test_mutex5);
|
||||
g_test_add_func ("/thread/mutex/errno", test_mutex_errno);
|
||||
|
||||
{
|
||||
guint i;
|
||||
|
Loading…
Reference in New Issue
Block a user