From 347000929de775ae6b975a2959f5fabe81d6f1f0 Mon Sep 17 00:00:00 2001 From: Paul Tan Date: Sun, 2 Mar 2014 17:51:14 +0800 Subject: [PATCH] unix: workaround broken pthread_sigmask on Android On android, if a call to `pthread_sigmask` fails with EINVAL, fallback to `sigprocmask`. This workarounds the broken behaviour of `pthread_sigmask` on Android versions < 4.1. See: * https://android.googlesource.com/platform/bionic/+/9bf330b5 * https://code.google.com/p/android/issues/detail?id=15337 This is implemented by replacing all calls of `pthread_sigmask` to a new function `uv__pthread_sigmask` which implements this fallback mechanism. --- include/pthread-fixes.h | 13 +++++++++++++ src/unix/pthread-fixes.c | 23 +++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/include/pthread-fixes.h b/include/pthread-fixes.h index 230ce317..88c6b669 100644 --- a/include/pthread-fixes.h +++ b/include/pthread-fixes.h @@ -56,4 +56,17 @@ int pthread_barrier_destroy(pthread_barrier_t *barrier); #endif /* defined(PTHREAD_BARRIER_SERIAL_THREAD) */ int pthread_yield(void); + +/* Workaround pthread_sigmask() returning EINVAL on versions < 4.1 by + * replacing all calls to pthread_sigmask with sigprocmask. See: + * https://android.googlesource.com/platform/bionic/+/9bf330b5 + * https://code.google.com/p/android/issues/detail?id=15337 + */ +int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); + +#ifdef pthread_sigmask +#undef pthread_sigmask +#endif +#define pthread_sigmask(how, set, oldset) uv__pthread_sigmask(how, set, oldset) + #endif /* GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H */ diff --git a/src/unix/pthread-fixes.c b/src/unix/pthread-fixes.c index 2e4c542b..dc54f35d 100644 --- a/src/unix/pthread-fixes.c +++ b/src/unix/pthread-fixes.c @@ -29,6 +29,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* Android versions < 4.1 have a broken pthread_sigmask. + * Note that this block of code must come before any inclusion of + * pthread-fixes.h so that the real pthread_sigmask can be referenced. + * */ +#include +#include + +int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset) { + static int workaround; + + if (workaround) { + return sigprocmask(how, set, oset); + } else if (pthread_sigmask(how, set, oset)) { + if (errno == EINVAL && sigprocmask(how, set, oset) == 0) { + workaround = 1; + return 0; + } else { + return -1; + } + } else { + return 0; + } +} /*Android doesn't provide pthread_barrier_t for now.*/ #ifndef PTHREAD_BARRIER_SERIAL_THREAD