diff options
-rw-r--r-- | libc/Android.bp | 1 | ||||
-rw-r--r-- | libc/bionic/fdsan.cpp | 12 | ||||
-rw-r--r-- | libc/bionic/pthread_sigqueue.cpp | 51 | ||||
-rw-r--r-- | libc/include/android/versioning.h | 16 | ||||
-rw-r--r-- | libc/include/signal.h | 4 | ||||
-rw-r--r-- | libc/include/sys/cdefs.h | 9 | ||||
-rw-r--r-- | libc/libc.arm.map | 1 | ||||
-rw-r--r-- | libc/libc.arm64.map | 1 | ||||
-rw-r--r-- | libc/libc.map.txt | 1 | ||||
-rw-r--r-- | libc/libc.mips.map | 1 | ||||
-rw-r--r-- | libc/libc.mips64.map | 1 | ||||
-rw-r--r-- | libc/libc.x86.map | 1 | ||||
-rw-r--r-- | libc/libc.x86_64.map | 1 | ||||
-rw-r--r-- | tests/signal_test.cpp | 36 |
14 files changed, 120 insertions, 16 deletions
diff --git a/libc/Android.bp b/libc/Android.bp index 61d00cd09..fe65acefa 100644 --- a/libc/Android.bp +++ b/libc/Android.bp @@ -1456,6 +1456,7 @@ cc_library_static { "bionic/pthread_mutex.cpp", "bionic/pthread_once.cpp", "bionic/pthread_rwlock.cpp", + "bionic/pthread_sigqueue.cpp", "bionic/pthread_self.cpp", "bionic/pthread_setname_np.cpp", "bionic/pthread_setschedparam.cpp", diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp index d877172d8..ad1ddee7c 100644 --- a/libc/bionic/fdsan.cpp +++ b/libc/bionic/fdsan.cpp @@ -176,12 +176,20 @@ __printflike(1, 0) static void fdsan_error(const char* fmt, ...) { return; } + struct { + size_t size; + char buf[512]; + } abort_message; + va_list va; va_start(va, fmt); if (error_level == ANDROID_FDSAN_ERROR_LEVEL_FATAL) { async_safe_fatal_va_list("fdsan", fmt, va); } else { async_safe_format_log_va_list(ANDROID_LOG_ERROR, "fdsan", fmt, va); + size_t len = + async_safe_format_buffer_va_list(abort_message.buf, sizeof(abort_message.buf), fmt, va); + abort_message.size = len + sizeof(size_t); } va_end(va); @@ -192,7 +200,9 @@ __printflike(1, 0) static void fdsan_error(const char* fmt, ...) { __BIONIC_FALLTHROUGH; case ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS: // DEBUGGER_SIGNAL - raise(__SIGRTMIN + 3); + sigval abort_msg; + abort_msg.sival_ptr = &abort_message; + pthread_sigqueue(pthread_self(), __SIGRTMIN + 3, abort_msg); break; case ANDROID_FDSAN_ERROR_LEVEL_FATAL: diff --git a/libc/bionic/pthread_sigqueue.cpp b/libc/bionic/pthread_sigqueue.cpp new file mode 100644 index 000000000..34bda38c4 --- /dev/null +++ b/libc/bionic/pthread_sigqueue.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <sys/syscall.h> +#include <unistd.h> + +#include "private/ErrnoRestorer.h" +#include "pthread_internal.h" + +int pthread_sigqueue(pthread_t t, int sig, const union sigval value) { + ErrnoRestorer errno_restorer; + + pid_t tid = pthread_gettid_np(t); + if (tid == -1) return ESRCH; + + siginfo_t siginfo; + siginfo.si_code = SI_QUEUE; + siginfo.si_pid = getpid(); + siginfo.si_uid = getuid(); + siginfo.si_value = value; + + return syscall(__NR_rt_tgsigqueueinfo, getpid(), tid, sig, &siginfo) ? errno : 0; +} diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h index 4e1a1854c..cab115602 100644 --- a/libc/include/android/versioning.h +++ b/libc/include/android/versioning.h @@ -17,15 +17,15 @@ #ifndef ANDROID_VERSIONING_H #define ANDROID_VERSIONING_H -#define __INTRODUCED_IN(api_level) __attribute__((annotate("introduced_in=" #api_level))) +#define __INTRODUCED_IN(api_level) __attribute__((annotate("introduced_in=" __STRING(api_level)))) #define __INTRODUCED_IN_FUTURE __attribute__((annotate("introduced_in_future"))) -#define __DEPRECATED_IN(api_level) __attribute__((annotate("deprecated_in=" #api_level))) -#define __REMOVED_IN(api_level) __attribute__((annotate("obsoleted_in=" #api_level))) -#define __INTRODUCED_IN_32(api_level) __attribute__((annotate("introduced_in_32=" #api_level))) -#define __INTRODUCED_IN_64(api_level) __attribute__((annotate("introduced_in_64=" #api_level))) -#define __INTRODUCED_IN_ARM(api_level) __attribute__((annotate("introduced_in_arm=" #api_level))) -#define __INTRODUCED_IN_X86(api_level) __attribute__((annotate("introduced_in_x86=" #api_level))) -#define __INTRODUCED_IN_MIPS(api_level) __attribute__((annotate("introduced_in_mips=" #api_level))) +#define __DEPRECATED_IN(api_level) __attribute__((annotate("deprecated_in=" __STRING(api_level)))) +#define __REMOVED_IN(api_level) __attribute__((annotate("obsoleted_in=" __STRING(api_level)))) +#define __INTRODUCED_IN_32(api_level) __attribute__((annotate("introduced_in_32=" __STRING(api_level)))) +#define __INTRODUCED_IN_64(api_level) __attribute__((annotate("introduced_in_64=" __STRING(api_level)))) +#define __INTRODUCED_IN_ARM(api_level) __attribute__((annotate("introduced_in_arm=" __STRING(api_level)))) +#define __INTRODUCED_IN_X86(api_level) __attribute__((annotate("introduced_in_x86=" __STRING(api_level)))) +#define __INTRODUCED_IN_MIPS(api_level) __attribute__((annotate("introduced_in_mips=" __STRING(api_level)))) #define __VERSIONER_NO_GUARD __attribute__((annotate("versioner_no_guard"))) diff --git a/libc/include/signal.h b/libc/include/signal.h index 00860d5e6..9d1030ac2 100644 --- a/libc/include/signal.h +++ b/libc/include/signal.h @@ -113,6 +113,10 @@ void psiginfo(const siginfo_t* __info, const char* __msg) __INTRODUCED_IN(17); void psignal(int __signal, const char* __msg) __INTRODUCED_IN(17); int pthread_kill(pthread_t __pthread, int __signal); +#if defined(__USE_GNU) +int pthread_sigqueue(pthread_t __pthread, int __signal, const union sigval __value) __INTRODUCED_IN(__ANDROID_API_Q__); +#endif + int pthread_sigmask(int __how, const sigset_t* __new_set, sigset_t* __old_set); int pthread_sigmask64(int __how, const sigset64_t* __new_set, sigset64_t* __old_set) __INTRODUCED_IN(28); diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h index 13ad4fe77..26a05c85c 100644 --- a/libc/include/sys/cdefs.h +++ b/libc/include/sys/cdefs.h @@ -38,7 +38,6 @@ #define _SYS_CDEFS_H_ #include <android/api-level.h> -#include <android/versioning.h> #define __BIONIC__ 1 @@ -92,7 +91,6 @@ #define ___STRING(x) __STRING(x) #define ___CONCAT(x,y) __CONCAT(x,y) -#if defined(__STDC__) || defined(__cplusplus) #define __P(protos) protos /* full-blown ANSI C */ #define __CONCAT1(x,y) x ## y #define __CONCAT(x,y) __CONCAT1(x,y) @@ -102,12 +100,9 @@ #define __inline inline /* convert to C++ keyword */ #endif /* !__cplusplus */ -#else /* !(__STDC__ || __cplusplus) */ -#define __P(protos) () /* traditional C preprocessor */ -#define __CONCAT(x,y) x/**/y -#define __STRING(x) "x" +#include <android/versioning.h> -#endif /* !(__STDC__ || __cplusplus) */ +#include <android/versioning.h> #define __always_inline __attribute__((__always_inline__)) #define __attribute_const__ __attribute__((__const__)) diff --git a/libc/libc.arm.map b/libc/libc.arm.map index f1eec3c6a..8fb07f784 100644 --- a/libc/libc.arm.map +++ b/libc/libc.arm.map @@ -1431,6 +1431,7 @@ LIBC_Q { # introduced=Q android_fdsan_get_tag_value; android_fdsan_get_error_level; android_fdsan_set_error_level; + pthread_sigqueue; timespec_get; } LIBC_P; diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map index 4d538cd64..8c5eb89d4 100644 --- a/libc/libc.arm64.map +++ b/libc/libc.arm64.map @@ -1352,6 +1352,7 @@ LIBC_Q { # introduced=Q android_fdsan_get_tag_value; android_fdsan_get_error_level; android_fdsan_set_error_level; + pthread_sigqueue; timespec_get; } LIBC_P; diff --git a/libc/libc.map.txt b/libc/libc.map.txt index 0f5abc0b9..c5f091076 100644 --- a/libc/libc.map.txt +++ b/libc/libc.map.txt @@ -1456,6 +1456,7 @@ LIBC_Q { # introduced=Q android_fdsan_get_tag_value; android_fdsan_get_error_level; android_fdsan_set_error_level; + pthread_sigqueue; timespec_get; } LIBC_P; diff --git a/libc/libc.mips.map b/libc/libc.mips.map index f14f73173..fbaf508f6 100644 --- a/libc/libc.mips.map +++ b/libc/libc.mips.map @@ -1415,6 +1415,7 @@ LIBC_Q { # introduced=Q android_fdsan_get_tag_value; android_fdsan_get_error_level; android_fdsan_set_error_level; + pthread_sigqueue; timespec_get; } LIBC_P; diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map index 4d538cd64..8c5eb89d4 100644 --- a/libc/libc.mips64.map +++ b/libc/libc.mips64.map @@ -1352,6 +1352,7 @@ LIBC_Q { # introduced=Q android_fdsan_get_tag_value; android_fdsan_get_error_level; android_fdsan_set_error_level; + pthread_sigqueue; timespec_get; } LIBC_P; diff --git a/libc/libc.x86.map b/libc/libc.x86.map index d44001e68..db86e5511 100644 --- a/libc/libc.x86.map +++ b/libc/libc.x86.map @@ -1413,6 +1413,7 @@ LIBC_Q { # introduced=Q android_fdsan_get_tag_value; android_fdsan_get_error_level; android_fdsan_set_error_level; + pthread_sigqueue; timespec_get; } LIBC_P; diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map index 4d538cd64..8c5eb89d4 100644 --- a/libc/libc.x86_64.map +++ b/libc/libc.x86_64.map @@ -1352,6 +1352,7 @@ LIBC_Q { # introduced=Q android_fdsan_get_tag_value; android_fdsan_get_error_level; android_fdsan_set_error_level; + pthread_sigqueue; timespec_get; } LIBC_P; diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp index cc95ef7b3..52a097bf3 100644 --- a/tests/signal_test.cpp +++ b/tests/signal_test.cpp @@ -597,6 +597,42 @@ TEST(signal, sigqueue) { ASSERT_EQ(1, g_sigqueue_signal_handler_call_count); } +TEST(signal, pthread_sigqueue_self) { + ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler, SA_SIGINFO); + sigval_t sigval; + sigval.sival_int = 1; + errno = 0; + ASSERT_EQ(0, pthread_sigqueue(pthread_self(), SIGALRM, sigval)); + ASSERT_EQ(0, errno); + ASSERT_EQ(1, g_sigqueue_signal_handler_call_count); +} + +TEST(signal, pthread_sigqueue_other) { + ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler, SA_SIGINFO); + sigval_t sigval; + sigval.sival_int = 1; + + sigset_t mask; + sigfillset(&mask); + pthread_sigmask(SIG_SETMASK, &mask, nullptr); + pthread_t thread; + int rc = pthread_create(&thread, nullptr, + [](void*) -> void* { + sigset_t mask; + sigemptyset(&mask); + sigsuspend(&mask); + return nullptr; + }, + nullptr); + ASSERT_EQ(0, rc); + + errno = 0; + ASSERT_EQ(0, pthread_sigqueue(thread, SIGALRM, sigval)); + ASSERT_EQ(0, errno); + pthread_join(thread, nullptr); + ASSERT_EQ(1, g_sigqueue_signal_handler_call_count); +} + TEST(signal, sigwaitinfo) { SignalMaskRestorer smr; |