diff options
author | Simon Rozsival <simon@rozsival.com> | 2022-03-10 23:31:16 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-10 23:31:16 +0300 |
commit | 1095bbd92dd3f2a6bc446a54445bffd6e2ecd212 (patch) | |
tree | 15570d89b687d4d37ce21c65dad6376748ca5cbd | |
parent | d77499132535b6beec3949e4dc412887361aa448 (diff) |
[release/6.0] [Android] Workaround for invalid return value from clock_nanosleep (#65372)
* [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
-rw-r--r-- | src/mono/mono/eglib/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/mono/mono/eglib/eglib-remap.h | 4 | ||||
-rw-r--r-- | src/mono/mono/eglib/gclock-nanosleep.c | 31 | ||||
-rw-r--r-- | src/mono/mono/eglib/gdate-unix.c | 2 | ||||
-rw-r--r-- | src/mono/mono/eglib/glib.h | 10 | ||||
-rw-r--r-- | src/mono/mono/mini/mini-posix.c | 5 | ||||
-rw-r--r-- | src/mono/mono/utils/mono-threads.c | 3 |
7 files changed, 55 insertions, 4 deletions
diff --git a/src/mono/mono/eglib/CMakeLists.txt b/src/mono/mono/eglib/CMakeLists.txt index 1325ee6c112..69bf7e18869 100644 --- a/src/mono/mono/eglib/CMakeLists.txt +++ b/src/mono/mono/eglib/CMakeLists.txt @@ -43,6 +43,10 @@ set(eglib_common_sources 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}") diff --git a/src/mono/mono/eglib/eglib-remap.h b/src/mono/mono/eglib/eglib-remap.h index c3e956842de..3af646a8e47 100644 --- a/src/mono/mono/eglib/eglib-remap.h +++ b/src/mono/mono/eglib/eglib-remap.h @@ -318,3 +318,7 @@ #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 diff --git a/src/mono/mono/eglib/gclock-nanosleep.c b/src/mono/mono/eglib/gclock-nanosleep.c new file mode 100644 index 00000000000..f2ced8b2c07 --- /dev/null +++ b/src/mono/mono/eglib/gclock-nanosleep.c @@ -0,0 +1,31 @@ +/* + * 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; +} diff --git a/src/mono/mono/eglib/gdate-unix.c b/src/mono/mono/eglib/gdate-unix.c index 53f4bbb3d5a..9a98e663045 100644 --- a/src/mono/mono/eglib/gdate-unix.c +++ b/src/mono/mono/eglib/gdate-unix.c @@ -64,7 +64,7 @@ g_usleep (gulong microseconds) } 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); diff --git a/src/mono/mono/eglib/glib.h b/src/mono/mono/eglib/glib.h index 5a454a03720..4c08f44732e 100644 --- a/src/mono/mono/eglib/glib.h +++ b/src/mono/mono/eglib/glib.h @@ -27,6 +27,7 @@ #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. @@ -1508,4 +1509,13 @@ mono_qsort (void* base, size_t num, size_t size, int (*compare)(const void*, con #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 diff --git a/src/mono/mono/mini/mini-posix.c b/src/mono/mono/mini/mini-posix.c index 346b4bd43f2..79bf8c84f88 100644 --- a/src/mono/mono/mini/mini-posix.c +++ b/src/mono/mono/mini/mini-posix.c @@ -79,6 +79,7 @@ #include <mono/component/debugger-agent.h> #include "mini-runtime.h" #include "jit-icalls.h" +#include <glib.h> #ifdef HOST_DARWIN #include <mach/mach.h> @@ -530,7 +531,7 @@ clock_init_for_profiler (MonoProfilerSampleMode mode) * 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; } @@ -554,7 +555,7 @@ clock_sleep_ns_abs (guint64 ns_abs) 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); diff --git a/src/mono/mono/utils/mono-threads.c b/src/mono/mono/utils/mono-threads.c index 52890fe288e..e26cc53e02c 100644 --- a/src/mono/mono/utils/mono-threads.c +++ b/src/mono/mono/utils/mono-threads.c @@ -33,6 +33,7 @@ #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> @@ -1743,7 +1744,7 @@ mono_thread_info_sleep (guint32 ms, gboolean *alerted) } 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); |