* [Android] Workaround for invalid return value from clock_nanosleep (#64679)
There used to be a bug in Android libc implementation of `clock_nanosleep`. The return value should be `errno` on errors but instead in it returns `-1` and sets `errno`. The libc (Bionic) bug [has been fixed](https://android-review.googlesource.com/c/platform/bionic/+/110652/) since Android 6 and newer but it causes problems to [customers who are unable to update Android on their devices](https://github.com/xamarin/xamarin-android/issues/6600#issuecomment-
1026023654).
Fixes https://github.com/xamarin/xamarin-android/issues/6600
* Account for incorrect implementation of clock_nanosleep in older Android libc
* Shorten comments
* Add g_clock_nanosleep function
* Add remap definition
* Fix build
* Make sure the extra check runs only on Android
* Make Windows builds happy
* Try making wasm builds happy
* Fix leftover direct call to clock_nanosleep
gunicode.c
unicode-data.h)
+if(HAVE_CLOCK_NANOSLEEP)
+list(APPEND eglib_common_sources gclock-nanosleep.c)
+endif()
+
addprefix(eglib_sources ../eglib/ "${eglib_platform_sources};${eglib_common_sources}")
add_library(eglib_objects OBJECT "${eglib_sources}")
#define g_ascii_charcmp monoeg_ascii_charcmp
#define g_ascii_charcasecmp monoeg_ascii_charcasecmp
#define g_warning_d monoeg_warning_d
+
+#ifdef HAVE_CLOCK_NANOSLEEP
+#define g_clock_nanosleep monoeg_clock_nanosleep
+#endif
--- /dev/null
+/*
+ * gclock_nanosleep.c: Clock nanosleep on platforms that have clock_nanosleep().
+ *
+ * Copyright 2022 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+*/
+
+#include <config.h>
+#include <glib.h>
+#include <errno.h>
+
+gint
+g_clock_nanosleep (clockid_t clockid, gint flags, const struct timespec *request, struct timespec *remain)
+{
+ gint ret = 0;
+
+#if defined(HAVE_CLOCK_NANOSLEEP) && !defined(__PASE__)
+ ret = clock_nanosleep (clockid, flags, request, remain);
+#else
+ g_assert_not_reached ();
+#endif
+
+#ifdef HOST_ANDROID
+ // Workaround for incorrect implementation of clock_nanosleep return value on old Android (<=5.1)
+ // See https://github.com/xamarin/xamarin-android/issues/6600
+ if (ret == -1)
+ ret = errno;
+#endif
+
+ return ret;
+}
}
do {
- ret = clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &target, NULL);
+ ret = g_clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &target, NULL);
if (ret != 0 && ret != EINTR)
g_error ("%s: clock_nanosleep () returned %d", __func__, ret);
} while (ret == EINTR);
#include <stdint.h>
#include <inttypes.h>
#include <eglib-config.h>
+#include <time.h>
// - Pointers should only be converted to or from pointer-sized integers.
// - Any size integer can be converted to any other size integer.
#define g_try_realloc(obj, size) (g_cast (monoeg_try_realloc ((obj), (size))))
#define g_memdup(mem, size) (g_cast (monoeg_g_memdup ((mem), (size))))
+/*
+ * Clock Nanosleep
+ */
+
+#ifdef HAVE_CLOCK_NANOSLEEP
+gint
+g_clock_nanosleep (clockid_t clockid, gint flags, const struct timespec *request, struct timespec *remain);
+#endif
+
#endif // __GLIB_H
#include <mono/component/debugger-agent.h>
#include "mini-runtime.h"
#include "jit-icalls.h"
+#include <glib.h>
#ifdef HOST_DARWIN
#include <mach/mach.h>
* CLOCK_PROCESS_CPUTIME_ID clock but don't actually support it. For
* those systems, we fall back to CLOCK_MONOTONIC if we get EINVAL.
*/
- if (clock_nanosleep (CLOCK_PROCESS_CPUTIME_ID, TIMER_ABSTIME, &ts, NULL) != EINVAL) {
+ if (g_clock_nanosleep (CLOCK_PROCESS_CPUTIME_ID, TIMER_ABSTIME, &ts, NULL) != EINVAL) {
sampling_clock = CLOCK_PROCESS_CPUTIME_ID;
break;
}
then.tv_nsec = ns_abs % 1000000000;
do {
- ret = clock_nanosleep (sampling_clock, TIMER_ABSTIME, &then, NULL);
+ ret = g_clock_nanosleep (sampling_clock, TIMER_ABSTIME, &then, NULL);
if (ret != 0 && ret != EINTR)
g_error ("%s: clock_nanosleep () returned %d", __func__, ret);
#include <mono/utils/mono-threads-debug.h>
#include <mono/utils/os-event.h>
#include <mono/utils/w32api.h>
+#include <glib.h>
#include <errno.h>
#include <mono/utils/mono-errno.h>
}
do {
- ret = clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &target, NULL);
+ ret = g_clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &target, NULL);
} while (ret != 0);
#elif HOST_WIN32
Sleep (ms);