From a2aa6667e1e4d214390d1051a5866d944032a710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Thu, 21 Apr 2022 15:41:25 +0300 Subject: [PATCH] mdbx: avoid 32-bit Bionic/Android hang within `pthread_mutex_lock()`. --- src/core.c | 4 ++-- src/lck-posix.c | 23 ++++++++++++++++++++++- src/osal.c | 4 ++-- src/osal.h | 15 +++++++++++++++ 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/core.c b/src/core.c index 31a75049..647975ca 100644 --- a/src/core.c +++ b/src/core.c @@ -1248,7 +1248,7 @@ static __inline void rthc_lock(void) { #if defined(_WIN32) || defined(_WIN64) EnterCriticalSection(&rthc_critical_section); #else - mdbx_ensure(nullptr, pthread_mutex_lock(&rthc_mutex) == 0); + mdbx_ensure(nullptr, mdbx_pthread_mutex_lock(&rthc_mutex) == 0); #endif } @@ -1596,7 +1596,7 @@ static __inline void lcklist_lock(void) { #if defined(_WIN32) || defined(_WIN64) EnterCriticalSection(&lcklist_critical_section); #else - mdbx_ensure(nullptr, pthread_mutex_lock(&lcklist_mutex) == 0); + mdbx_ensure(nullptr, mdbx_pthread_mutex_lock(&lcklist_mutex) == 0); #endif } diff --git a/src/lck-posix.c b/src/lck-posix.c index 36522ac8..5753fdf1 100644 --- a/src/lck-posix.c +++ b/src/lck-posix.c @@ -812,11 +812,32 @@ __cold static int mdbx_ipclock_failed(MDBX_env *env, mdbx_ipclock_t *ipc, return rc; } +#if defined(__ANDROID_API__) || defined(ANDROID) || defined(BIONIC) +MDBX_INTERNAL_FUNC int mdbx_check_tid4bionic(void) { + /* avoid 32-bit Bionic bug/hang with 32-pit TID */ + if (sizeof(pthread_mutex_t) < sizeof(pid_t) + sizeof(unsigned)) { + pid_t tid = gettid(); + if (unlikely(tid > 0xffff)) { + mdbx_fatal("Raise the ENOSYS(%d) error to avoid hang due " + "the 32-bit Bionic/Android bug with tid/thread_id 0x%08x(%i) " + "that don’t fit in 16 bits, see " + "https://android.googlesource.com/platform/bionic/+/master/" + "docs/32-bit-abi.md#is-too-small-for-large-pids", + ENOSYS, tid, tid); + return ENOSYS; + } + } + return 0; +} +#endif /* __ANDROID_API__ || ANDROID) || BIONIC */ + static int mdbx_ipclock_lock(MDBX_env *env, mdbx_ipclock_t *ipc, const bool dont_wait) { #if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \ MDBX_LOCKING == MDBX_LOCKING_POSIX2008 - int rc = dont_wait ? pthread_mutex_trylock(ipc) : pthread_mutex_lock(ipc); + int rc = mdbx_check_tid4bionic(); + if (likely(rc == 0)) + rc = dont_wait ? pthread_mutex_trylock(ipc) : pthread_mutex_lock(ipc); rc = (rc == EBUSY && dont_wait) ? MDBX_BUSY : rc; #elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988 int rc = MDBX_SUCCESS; diff --git a/src/osal.c b/src/osal.c index f0cb13b5..2a5cac7a 100644 --- a/src/osal.c +++ b/src/osal.c @@ -437,7 +437,7 @@ MDBX_INTERNAL_FUNC int mdbx_condpair_lock(mdbx_condpair_t *condpair) { DWORD code = WaitForSingleObject(condpair->mutex, INFINITE); return waitstatus2errcode(code); #else - return pthread_mutex_lock(&condpair->mutex); + return mdbx_pthread_mutex_lock(&condpair->mutex); #endif } @@ -507,7 +507,7 @@ MDBX_INTERNAL_FUNC int mdbx_fastmutex_acquire(mdbx_fastmutex_t *fastmutex) { } return MDBX_SUCCESS; #else - return pthread_mutex_lock(fastmutex); + return mdbx_pthread_mutex_lock(fastmutex); #endif } diff --git a/src/osal.h b/src/osal.h index ec7b0219..31a5d1a7 100644 --- a/src/osal.h +++ b/src/osal.h @@ -730,6 +730,7 @@ MDBX_MAYBE_UNUSED static __inline uint32_t mdbx_getpid(void) { #if defined(_WIN32) || defined(_WIN64) return GetCurrentProcessId(); #else + STATIC_ASSERT(sizeof(pid_t) <= sizeof(uint32_t)); return getpid(); #endif } @@ -745,6 +746,20 @@ MDBX_MAYBE_UNUSED static __inline uintptr_t mdbx_thread_self(void) { return (uintptr_t)thunk; } +#if !defined(_WIN32) && !defined(_WIN64) +#if defined(__ANDROID_API__) || defined(ANDROID) || defined(BIONIC) +MDBX_INTERNAL_FUNC int mdbx_check_tid4bionic(void); +#else +static __inline int mdbx_check_tid4bionic(void) { return 0; } +#endif /* __ANDROID_API__ || ANDROID) || BIONIC */ + +MDBX_MAYBE_UNUSED static __inline int +mdbx_pthread_mutex_lock(pthread_mutex_t *mutex) { + int err = mdbx_check_tid4bionic(); + return unlikely(err) ? err : pthread_mutex_lock(mutex); +} +#endif /* !Windows */ + MDBX_INTERNAL_FUNC uint64_t mdbx_osal_monotime(void); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16);