diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h @@ -49,7 +49,18 @@ uptr internal_sigaltstack(const void* ss, void* oss); uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset); -#if SANITIZER_GLIBC + +void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset); +struct ScopedBlockSignals { + ScopedBlockSignals(); + ~ScopedBlockSignals(); + void GetSavedSet(__sanitizer_sigset_t *set); + + private: + __sanitizer_sigset_t saved_; +}; + +# if SANITIZER_GLIBC uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp); #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -842,6 +842,27 @@ #endif } +void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *old) { + CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, set, old)); +} +ScopedBlockSignals::ScopedBlockSignals() { + __sanitizer_sigset_t set; + internal_sigfillset(&set); +# if SANITIZER_LINUX && !SANITIZER_ANDROID + // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked + // on any thread, setuid call hangs. + // See test/sanitizer_common/TestCases/Linux/setuid.c. + internal_sigdelset(&set, 33); +# endif + SetSigProcMask(&set, &saved_); +} + +void ScopedBlockSignals::GetSavedSet(__sanitizer_sigset_t *set) { + internal_memcpy(set, &saved_, sizeof(saved_)); +} + +ScopedBlockSignals::~ScopedBlockSignals() { SetSigProcMask(&saved_, nullptr); } + void internal_sigfillset(__sanitizer_sigset_t *set) { internal_memset(set, 0xff, sizeof(*set)); } @@ -1741,18 +1762,9 @@ #if !SANITIZER_GO void *internal_start_thread(void *(*func)(void *arg), void *arg) { // Start the thread with signals blocked, otherwise it can steal user signals. - __sanitizer_sigset_t set, old; - internal_sigfillset(&set); -#if SANITIZER_LINUX && !SANITIZER_ANDROID - // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked - // on any thread, setuid call hangs. - // See test/sanitizer_common/TestCases/Linux/setuid.c. - internal_sigdelset(&set, 33); -#endif - internal_sigprocmask(SIG_SETMASK, &set, &old); + ScopedBlockSignals block; void *th; real_pthread_create(&th, nullptr, func, arg); - internal_sigprocmask(SIG_SETMASK, &old, nullptr); return th; }