diff options
35 files changed, 818 insertions, 415 deletions
diff --git a/docs/32-bit-abi.md b/docs/32-bit-abi.md index 9ae19734a..21f9b7137 100644 --- a/docs/32-bit-abi.md +++ b/docs/32-bit-abi.md @@ -64,7 +64,9 @@ In the 64-bit ABI, `off_t` is always 64-bit. On 32-bit Android, `sigset_t` is too small for ARM and x86 (but correct for MIPS). This means that there is no support for real-time signals in 32-bit -code. +code. Android P (API level 28) adds `sigset64_t` and a corresponding function +for every function that takes a `sigset_t` (so `sigprocmask64` takes a +`sigset64_t` where `sigprocmask` takes a `sigset_t`). In the 64-bit ABI, `sigset_t` is the correct size for every architecture. @@ -77,10 +79,11 @@ Android all use the 32-bit `time_t`. In the 64-bit ABI, `time_t` is 64-bit. + ## `pthread_mutex_t` is too small for large pids This doesn't generally affect Android devices, because on devices -`/proc/sys/kernel/pid_max` is usually too small to hit the 16-bit limit, +`/proc/sys/kernel/pid_max` is usually too small to hit our 16-bit limit, but 32-bit bionic's `pthread_mutex` is a total of 32 bits, leaving just 16 bits for the owner thread id. This means bionic isn't able to support mutexes for tids that don't fit in 16 bits. This typically manifests as diff --git a/libc/Android.bp b/libc/Android.bp index 2ea851466..0f5820459 100644 --- a/libc/Android.bp +++ b/libc/Android.bp @@ -1248,9 +1248,6 @@ cc_library_static { "bionic/dirent.cpp", "bionic/dup2.cpp", "bionic/environ.cpp", - "bionic/epoll_create.cpp", - "bionic/epoll_pwait.cpp", - "bionic/epoll_wait.cpp", "bionic/error.cpp", "bionic/eventfd_read.cpp", "bionic/eventfd_write.cpp", @@ -1350,6 +1347,7 @@ cc_library_static { "bionic/swab.cpp", "bionic/symlink.cpp", "bionic/sync_file_range.cpp", + "bionic/sys_epoll.cpp", "bionic/sys_msg.cpp", "bionic/sys_sem.cpp", "bionic/sys_shm.cpp", @@ -1431,7 +1429,6 @@ cc_library_static { "bionic/pthread_self.cpp", "bionic/pthread_setname_np.cpp", "bionic/pthread_setschedparam.cpp", - "bionic/pthread_sigmask.cpp", "bionic/pthread_spinlock.cpp", // The following implementations depend on pthread data or implementation, diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT index 5c9a284fe..5c63c0f17 100644 --- a/libc/SYSCALLS.TXT +++ b/libc/SYSCALLS.TXT @@ -229,12 +229,12 @@ int clock_adjtime(clockid_t, struct timex*) all # signals int __sigaction:sigaction(int, const struct sigaction*, struct sigaction*) arm,mips,x86 int __rt_sigaction:rt_sigaction(int, const struct sigaction*, struct sigaction*, size_t) all -int __rt_sigpending:rt_sigpending(sigset_t*, size_t) all -int __rt_sigprocmask:rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t) all -int __rt_sigsuspend:rt_sigsuspend(const sigset_t*, size_t) all -int __rt_sigtimedwait:rt_sigtimedwait(const sigset_t*, siginfo_t*, const timespec*, size_t) all +int __rt_sigpending:rt_sigpending(sigset64_t*, size_t) all +int __rt_sigprocmask:rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t) all +int __rt_sigsuspend:rt_sigsuspend(const sigset64_t*, size_t) all +int __rt_sigtimedwait:rt_sigtimedwait(const sigset64_t*, siginfo_t*, const timespec*, size_t) all int ___rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*) all -int __signalfd4:signalfd4(int, const sigset_t*, size_t, int) all +int __signalfd4:signalfd4(int, const sigset64_t*, size_t, int) all # sockets int __socket:socket(int, int, int) arm,arm64,mips,mips64,x86_64 @@ -305,7 +305,7 @@ ssize_t vmsplice(int, const struct iovec*, size_t, unsigned int) all int epoll_create1(int) all int epoll_ctl(int, int op, int, struct epoll_event*) all -int __epoll_pwait:epoll_pwait(int, struct epoll_event*, int, int, const sigset_t*, size_t) all +int __epoll_pwait:epoll_pwait(int, struct epoll_event*, int, int, const sigset64_t*, size_t) all int eventfd:eventfd2(unsigned int, int) all @@ -317,7 +317,7 @@ int inotify_add_watch(int, const char*, unsigned int) all int inotify_rm_watch(int, unsigned int) all int __pselect6:pselect6(int, fd_set*, fd_set*, fd_set*, timespec*, void*) all -int __ppoll:ppoll(pollfd*, unsigned int, timespec*, const sigset_t*, size_t) all +int __ppoll:ppoll(pollfd*, unsigned int, timespec*, const sigset64_t*, size_t) all ssize_t process_vm_readv(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long) all ssize_t process_vm_writev(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long) all diff --git a/libc/bionic/abort.cpp b/libc/bionic/abort.cpp index 9f1c31f3d..ec26a50c4 100644 --- a/libc/bionic/abort.cpp +++ b/libc/bionic/abort.cpp @@ -32,8 +32,6 @@ #include <sys/syscall.h> #include <unistd.h> -#include "private/kernel_sigset_t.h" - // We call tgkill(2) directly instead of raise (or even the libc tgkill wrapper), to reduce the // number of uninteresting stack frames at the top of a crash. static inline __always_inline void inline_tgkill(pid_t pid, pid_t tid, int sig) { @@ -62,11 +60,11 @@ void abort() { // Don't block SIGABRT to give any signal handler a chance; we ignore // any errors -- X311J doesn't allow abort to return anyway. - kernel_sigset_t mask; - mask.fill(); - mask.clear(SIGABRT); - __rt_sigprocmask(SIG_SETMASK, &mask, nullptr, sizeof(mask)); + sigset64_t mask; + sigfillset64(&mask); + sigdelset64(&mask, SIGABRT); + sigprocmask64(SIG_SETMASK, &mask, nullptr); inline_tgkill(pid, tid, SIGABRT); // If SIGABRT ignored, or caught and the handler returns, @@ -76,8 +74,8 @@ void abort() { sa.sa_flags = SA_RESTART; sigemptyset(&sa.sa_mask); sigaction(SIGABRT, &sa, &sa); - __rt_sigprocmask(SIG_SETMASK, &mask, nullptr, sizeof(mask)); + sigprocmask64(SIG_SETMASK, &mask, nullptr); inline_tgkill(pid, tid, SIGABRT); // If we get this far, just exit. diff --git a/libc/bionic/epoll_wait.cpp b/libc/bionic/epoll_wait.cpp deleted file mode 100644 index deb19daf2..000000000 --- a/libc/bionic/epoll_wait.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2013 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 <sys/epoll.h> - -int epoll_wait(int fd, struct epoll_event* events, int max_events, int timeout) { - return epoll_pwait(fd, events, max_events, timeout, NULL); -} diff --git a/libc/bionic/pause.cpp b/libc/bionic/pause.cpp index 2a0779a5c..534a80430 100644 --- a/libc/bionic/pause.cpp +++ b/libc/bionic/pause.cpp @@ -26,12 +26,10 @@ * SUCH DAMAGE. */ +#include <signal.h> #include <unistd.h> -#include "private/kernel_sigset_t.h" - int pause() { - kernel_sigset_t mask; - if (__rt_sigprocmask(SIG_SETMASK, nullptr, &mask, sizeof(mask)) == -1) return -1; - return __rt_sigsuspend(&mask, sizeof(mask)); + sigset64_t mask = {}; + return sigsuspend64(&mask); } diff --git a/libc/bionic/poll.cpp b/libc/bionic/poll.cpp index dbc9584e9..1d72fe5b4 100644 --- a/libc/bionic/poll.cpp +++ b/libc/bionic/poll.cpp @@ -31,51 +31,56 @@ #include <sys/select.h> #include "private/bionic_time_conversions.h" -#include "private/kernel_sigset_t.h" +#include "private/SigSetConverter.h" -extern "C" int __ppoll(pollfd*, unsigned int, timespec*, const kernel_sigset_t*, size_t); +extern "C" int __ppoll(pollfd*, unsigned int, timespec*, const sigset64_t*, size_t); extern "C" int __pselect6(int, fd_set*, fd_set*, fd_set*, timespec*, void*); int poll(pollfd* fds, nfds_t fd_count, int ms) __overloadable { timespec ts; - timespec* ts_ptr = NULL; + timespec* ts_ptr = nullptr; if (ms >= 0) { timespec_from_ms(ts, ms); ts_ptr = &ts; } - return __ppoll(fds, fd_count, ts_ptr, NULL, 0); + return __ppoll(fds, fd_count, ts_ptr, nullptr, 0); } int ppoll(pollfd* fds, nfds_t fd_count, const timespec* ts, const sigset_t* ss) __overloadable { + // The underlying `__ppoll` system call only takes `sigset64_t`. + SigSetConverter set; + sigset64_t* ss_ptr = nullptr; + if (ss != nullptr) { + set = {}; + set.sigset = *ss; + ss_ptr = &set.sigset64; + } + return ppoll64(fds, fd_count, ts, ss_ptr); +} + +int ppoll64(pollfd* fds, nfds_t fd_count, const timespec* ts, const sigset64_t* ss) { + // The underlying __ppoll system call modifies its `struct timespec` argument. timespec mutable_ts; - timespec* mutable_ts_ptr = NULL; - if (ts != NULL) { + timespec* mutable_ts_ptr = nullptr; + if (ts != nullptr) { mutable_ts = *ts; mutable_ts_ptr = &mutable_ts; } - - kernel_sigset_t kernel_ss; - kernel_sigset_t* kernel_ss_ptr = NULL; - if (ss != NULL) { - kernel_ss.set(ss); - kernel_ss_ptr = &kernel_ss; - } - - return __ppoll(fds, fd_count, mutable_ts_ptr, kernel_ss_ptr, sizeof(kernel_ss)); + return __ppoll(fds, fd_count, mutable_ts_ptr, ss, sizeof(*ss)); } int select(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds, timeval* tv) { timespec ts; - timespec* ts_ptr = NULL; - if (tv != NULL) { + timespec* ts_ptr = nullptr; + if (tv != nullptr) { if (!timespec_from_timeval(ts, *tv)) { errno = EINVAL; return -1; } ts_ptr = &ts; } - int result = __pselect6(fd_count, read_fds, write_fds, error_fds, ts_ptr, NULL); - if (tv != NULL) { + int result = __pselect6(fd_count, read_fds, write_fds, error_fds, ts_ptr, nullptr); + if (tv != nullptr) { timeval_from_timespec(*tv, ts); } return result; @@ -83,20 +88,27 @@ int select(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds, int pselect(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds, const timespec* ts, const sigset_t* ss) { + // The underlying `__pselect6` system call only takes `sigset64_t`. + SigSetConverter set; + sigset64_t* ss_ptr = nullptr; + if (ss != nullptr) { + set = {}; + set.sigset = *ss; + ss_ptr = &set.sigset64; + } + return pselect64(fd_count, read_fds, write_fds, error_fds, ts, ss_ptr); +} + +int pselect64(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds, + const timespec* ts, const sigset64_t* ss) { + // The underlying __pselect6 system call modifies its `struct timespec` argument. timespec mutable_ts; - timespec* mutable_ts_ptr = NULL; - if (ts != NULL) { + timespec* mutable_ts_ptr = nullptr; + if (ts != nullptr) { mutable_ts = *ts; mutable_ts_ptr = &mutable_ts; } - kernel_sigset_t kernel_ss; - kernel_sigset_t* kernel_ss_ptr = NULL; - if (ss != NULL) { - kernel_ss.set(ss); - kernel_ss_ptr = &kernel_ss; - } - // The Linux kernel only handles 6 arguments and this system call really needs 7, // so the last argument is a void* pointing to: struct pselect6_extra_data_t { @@ -104,8 +116,8 @@ int pselect(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds size_t ss_len; }; pselect6_extra_data_t extra_data; - extra_data.ss_addr = reinterpret_cast<uintptr_t>(kernel_ss_ptr); - extra_data.ss_len = sizeof(kernel_ss); + extra_data.ss_addr = reinterpret_cast<uintptr_t>(ss); + extra_data.ss_len = sizeof(*ss); return __pselect6(fd_count, read_fds, write_fds, error_fds, mutable_ts_ptr, &extra_data); } diff --git a/libc/bionic/posix_timers.cpp b/libc/bionic/posix_timers.cpp index e3bb112fb..2edfe9701 100644 --- a/libc/bionic/posix_timers.cpp +++ b/libc/bionic/posix_timers.cpp @@ -26,8 +26,6 @@ * SUCH DAMAGE. */ -#include "private/kernel_sigset_t.h" - #include <errno.h> #include <malloc.h> #include <pthread.h> @@ -37,7 +35,6 @@ #include <time.h> // System calls. -extern "C" int __rt_sigtimedwait(const sigset_t*, siginfo_t*, const timespec*, size_t); extern "C" int __timer_create(clockid_t, sigevent*, __kernel_timer_t*); extern "C" int __timer_delete(__kernel_timer_t); extern "C" int __timer_getoverrun(__kernel_timer_t); @@ -74,16 +71,13 @@ static __kernel_timer_t to_kernel_timer_id(timer_t timer) { static void* __timer_thread_start(void* arg) { PosixTimer* timer = reinterpret_cast<PosixTimer*>(arg); - kernel_sigset_t sigset{TIMER_SIGNAL}; + sigset64_t sigset = {}; + sigaddset64(&sigset, TIMER_SIGNAL); while (true) { // Wait for a signal... - siginfo_t si; - memset(&si, 0, sizeof(si)); - int rc = __rt_sigtimedwait(sigset.get(), &si, NULL, sizeof(sigset)); - if (rc == -1) { - continue; - } + siginfo_t si = {}; + if (sigtimedwait64(&sigset, &si, nullptr) == -1) continue; if (si.si_code == SI_TIMER) { // This signal was sent because a timer fired, so call the callback. @@ -149,13 +143,14 @@ int timer_create(clockid_t clock_id, sigevent* evp, timer_t* timer_id) { // We start the thread with TIMER_SIGNAL blocked by blocking the signal here and letting it // inherit. If it tried to block the signal itself, there would be a race. - kernel_sigset_t sigset{TIMER_SIGNAL}; - kernel_sigset_t old_sigset; - __rt_sigprocmask(SIG_BLOCK, &sigset, &old_sigset, sizeof(sigset)); + sigset64_t sigset = {}; + sigaddset64(&sigset, TIMER_SIGNAL); + sigset64_t old_sigset; + sigprocmask64(SIG_BLOCK, &sigset, &old_sigset); int rc = pthread_create(&timer->callback_thread, &thread_attributes, __timer_thread_start, timer); - __rt_sigprocmask(SIG_SETMASK, &old_sigset, nullptr, sizeof(sigset)); + sigprocmask64(SIG_SETMASK, &old_sigset, nullptr); if (rc != 0) { free(timer); diff --git a/libc/bionic/signal.cpp b/libc/bionic/signal.cpp index 9a2341604..099944ad8 100644 --- a/libc/bionic/signal.cpp +++ b/libc/bionic/signal.cpp @@ -30,19 +30,36 @@ #include <pthread.h> #include <signal.h> #include <string.h> +#include <sys/epoll.h> +#include <sys/signalfd.h> #include <sys/types.h> #include <time.h> #include <unistd.h> -#include "private/kernel_sigset_t.h" +#include "private/ErrnoRestorer.h" +#include "private/SigSetConverter.h" +extern "C" int __rt_sigpending(const sigset64_t*, size_t); +extern "C" int __rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t); extern "C" int ___rt_sigqueueinfo(pid_t, int, siginfo_t*); -extern "C" int __rt_sigtimedwait(const sigset_t*, siginfo_t*, const timespec*, size_t); +extern "C" int __rt_sigsuspend(const sigset64_t*, size_t); +extern "C" int __rt_sigtimedwait(const sigset64_t*, siginfo_t*, const timespec*, size_t); -int sigaddset(sigset_t* set, int signum) { - int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0. +int pthread_sigmask(int how, const sigset_t* new_set, sigset_t* old_set) { + ErrnoRestorer errno_restorer; + return (sigprocmask(how, new_set, old_set) == -1) ? errno : 0; +} + +int pthread_sigmask64(int how, const sigset64_t* new_set, sigset64_t* old_set) { + ErrnoRestorer errno_restorer; + return (sigprocmask64(how, new_set, old_set) == -1) ? errno : 0; +} + +template <typename SigSetT> +int SigAddSet(SigSetT* set, int sig) { + int bit = sig - 1; // Signal numbers start at 1, but bit positions start at 0. unsigned long* local_set = reinterpret_cast<unsigned long*>(set); - if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) { + if (set == nullptr || bit < 0 || bit >= static_cast<int>(8*sizeof(*set))) { errno = EINVAL; return -1; } @@ -50,24 +67,28 @@ int sigaddset(sigset_t* set, int signum) { return 0; } -// This isn't in our header files, but is exposed on all architectures. -extern "C" int sigblock(int mask) { - union { - int mask; - sigset_t set; - } in, out; +int sigaddset(sigset_t* set, int sig) { + return SigAddSet(set, sig); +} - sigemptyset(&in.set); - in.mask = mask; +int sigaddset64(sigset64_t* set, int sig) { + return SigAddSet(set, sig); +} - if (sigprocmask(SIG_BLOCK, &in.set, &out.set) == -1) return -1; - return out.mask; +// This isn't in our header files, but is exposed on all architectures. +extern "C" int sigblock(int mask) { + SigSetConverter in, out; + sigemptyset(&in.sigset); + in.bsd = mask; + if (sigprocmask(SIG_BLOCK, &in.sigset, &out.sigset) == -1) return -1; + return out.bsd; } -int sigdelset(sigset_t* set, int signum) { - int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0. +template <typename SigSetT> +int SigDelSet(SigSetT* set, int sig) { + int bit = sig - 1; // Signal numbers start at 1, but bit positions start at 0. unsigned long* local_set = reinterpret_cast<unsigned long*>(set); - if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) { + if (set == nullptr || bit < 0 || bit >= static_cast<int>(8*sizeof(*set))) { errno = EINVAL; return -1; } @@ -75,29 +96,54 @@ int sigdelset(sigset_t* set, int signum) { return 0; } -int sigemptyset(sigset_t* set) { - if (set == NULL) { +int sigdelset(sigset_t* set, int sig) { + return SigDelSet(set, sig); +} + +int sigdelset64(sigset64_t* set, int sig) { + return SigDelSet(set, sig); +} + +template <typename SigSetT> +int SigEmptySet(SigSetT* set) { + if (set == nullptr) { errno = EINVAL; return -1; } - memset(set, 0, sizeof(sigset_t)); + memset(set, 0, sizeof(*set)); return 0; } -int sigfillset(sigset_t* set) { - if (set == NULL) { +int sigemptyset(sigset_t* set) { + return SigEmptySet(set); +} + +int sigemptyset64(sigset64_t* set) { + return SigEmptySet(set); +} + +template <typename SigSetT> +int SigFillSet(SigSetT* set) { + if (set == nullptr) { errno = EINVAL; return -1; } - memset(set, ~0, sizeof(sigset_t)); + memset(set, 0xff, sizeof(*set)); return 0; } +int sigfillset(sigset_t* set) { + return SigFillSet(set); +} + +int sigfillset64(sigset64_t* set) { + return SigFillSet(set); +} + int sighold(int sig) { - kernel_sigset_t set; - set.clear(); - if (!set.set(sig)) return -1; - return __rt_sigprocmask(SIG_BLOCK, &set, nullptr, sizeof(set)); + sigset64_t set = {}; + if (sigaddset64(&set, sig) == -1) return -1; + return sigprocmask64(SIG_BLOCK, &set, nullptr); } int sigignore(int sig) { @@ -119,87 +165,100 @@ int siginterrupt(int sig, int flag) { return sigaction(sig, &act, nullptr); } -int sigismember(const sigset_t* set, int signum) { - int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0. +template <typename SigSetT> +int SigIsMember(const SigSetT* set, int sig) { + int bit = sig - 1; // Signal numbers start at 1, but bit positions start at 0. const unsigned long* local_set = reinterpret_cast<const unsigned long*>(set); - if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) { + if (set == nullptr || bit < 0 || bit >= static_cast<int>(8*sizeof(*set))) { errno = EINVAL; return -1; } return static_cast<int>((local_set[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1); } -__LIBC_HIDDEN__ sighandler_t _signal(int signum, sighandler_t handler, int flags) { +int sigismember(const sigset_t* set, int sig) { + return SigIsMember(set, sig); +} + +int sigismember64(const sigset64_t* set, int sig) { + return SigIsMember(set, sig); +} + +__LIBC_HIDDEN__ sighandler_t _signal(int sig, sighandler_t handler, int flags) { struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_handler = handler; sa.sa_flags = flags; - if (sigaction(signum, &sa, &sa) == -1) { + if (sigaction(sig, &sa, &sa) == -1) { return SIG_ERR; } return sa.sa_handler; } -sighandler_t signal(int signum, sighandler_t handler) { - return _signal(signum, handler, SA_RESTART); +sighandler_t signal(int sig, sighandler_t handler) { + return _signal(sig, handler, SA_RESTART); } int sigpause(int sig) { - kernel_sigset_t set; - set.clear(); - if (__rt_sigprocmask(SIG_SETMASK, nullptr, &set, sizeof(set)) == -1) return -1; - if (!set.clear(sig)) return -1; - return __rt_sigsuspend(&set, sizeof(set)); + sigset64_t set = {}; + if (sigprocmask64(SIG_SETMASK, nullptr, &set) == -1 || sigdelset64(&set, sig) == -1) return -1; + return sigsuspend64(&set); } int sigpending(sigset_t* bionic_set) { - kernel_sigset_t set; - int result = __rt_sigpending(&set, sizeof(set)); - if (result != -1) { - *bionic_set = set.bionic; - } - return result; + SigSetConverter set = {}; + set.sigset = *bionic_set; + if (__rt_sigpending(&set.sigset64, sizeof(set.sigset64)) == -1) return -1; + *bionic_set = set.sigset; + return 0; +} + +int sigpending64(sigset64_t* set) { + return __rt_sigpending(set, sizeof(*set)); } int sigprocmask(int how, const sigset_t* bionic_new_set, sigset_t* bionic_old_set) { - kernel_sigset_t new_set; - kernel_sigset_t* new_set_ptr = NULL; - if (bionic_new_set != NULL) { - new_set.set(bionic_new_set); - new_set_ptr = &new_set; + SigSetConverter new_set; + sigset64_t* new_set_ptr = nullptr; + if (bionic_new_set != nullptr) { + sigemptyset64(&new_set.sigset64); + new_set.sigset = *bionic_new_set; + new_set_ptr = &new_set.sigset64; } - kernel_sigset_t old_set; - if (__rt_sigprocmask(how, new_set_ptr, &old_set, sizeof(old_set)) == -1) { + SigSetConverter old_set; + if (sigprocmask64(how, new_set_ptr, &old_set.sigset64) == -1) { return -1; } - if (bionic_old_set != NULL) { - *bionic_old_set = old_set.bionic; + if (bionic_old_set != nullptr) { + *bionic_old_set = old_set.sigset; } return 0; } -int sigqueue(pid_t pid, int signo, const sigval value) { +int sigprocmask64(int how, const sigset64_t* new_set, sigset64_t* old_set) { + return __rt_sigprocmask(how, new_set, old_set, sizeof(*new_set)); +} + +int sigqueue(pid_t pid, int sig, const sigval value) { siginfo_t info; memset(&info, 0, sizeof(siginfo_t)); - info.si_signo = signo; + info.si_signo = sig; info.si_code = SI_QUEUE; info.si_pid = getpid(); info.si_uid = getuid(); info.si_value = value; - - return ___rt_sigqueueinfo(pid, signo, &info); + return ___rt_sigqueueinfo(pid, sig, &info); } int sigrelse(int sig) { - kernel_sigset_t set; - set.clear(); - if (!set.set(sig)) return -1; - return __rt_sigprocmask(SIG_UNBLOCK, &set, nullptr, sizeof(set)); + sigset64_t set = {}; + if (sigaddset64(&set, sig) == -1) return -1; + return sigprocmask64(SIG_UNBLOCK, &set, nullptr); } sighandler_t sigset(int sig, sighandler_t disp) { @@ -215,57 +274,68 @@ sighandler_t sigset(int sig, sighandler_t disp) { return SIG_ERR; } - kernel_sigset_t new_mask{sig}; - kernel_sigset_t old_mask; - if (__rt_sigprocmask(disp == SIG_HOLD ? SIG_BLOCK : SIG_UNBLOCK, &new_mask, &old_mask, - sizeof(new_mask)) == -1) { + sigset64_t new_mask = {}; + sigaddset64(&new_mask, sig); + sigset64_t old_mask; + if (sigprocmask64(disp == SIG_HOLD ? SIG_BLOCK : SIG_UNBLOCK, &new_mask, &old_mask) == -1) { return SIG_ERR; } - return old_mask.is_set(sig) ? SIG_HOLD : old_sa.sa_handler; + return sigismember64(&old_mask, sig) ? SIG_HOLD : old_sa.sa_handler; } // This isn't in our header files, but is exposed on all architectures. extern "C" int sigsetmask(int mask) { - union { - int mask; - sigset_t set; - } in, out; + SigSetConverter in, out; + sigemptyset(&in.sigset); + in.bsd = mask; + if (sigprocmask(SIG_SETMASK, &in.sigset, &out.sigset) == -1) return -1; + return out.bsd; +} - sigemptyset(&in.set); - in.mask = mask; +int sigsuspend(const sigset_t* bionic_set) { + SigSetConverter set = {}; + set.sigset = *bionic_set; + return __rt_sigsuspend(&set.sigset64, sizeof(set.sigset64)); +} - if (sigprocmask(SIG_SETMASK, &in.set, &out.set) == -1) return -1; - return out.mask; +int sigsuspend64(const sigset64_t* set) { + return __rt_sigsuspend(set, sizeof(*set)); } -int sigsuspend(const sigset_t* bionic_set) { - kernel_sigset_t set(bionic_set); - return __rt_sigsuspend(&set, sizeof(set)); +int sigtimedwait(const sigset_t* bionic_set, siginfo_t* info, const timespec* timeout) { + SigSetConverter set = {}; + set.sigset = *bionic_set; + return __rt_sigtimedwait(&set.sigset64, info, timeout, sizeof(set.sigset64)); } -int sigtimedwait(const sigset_t* set, siginfo_t* info, const timespec* timeout) { - kernel_sigset_t sigset(set); - return __rt_sigtimedwait(sigset.get(), info, timeout, sizeof(sigset)); +int sigtimedwait64(const sigset64_t* set, siginfo_t* info, const timespec* timeout) { + return __rt_sigtimedwait(set, info, timeout, sizeof(*set)); } -int sigwait(const sigset_t* set, int* sig) { - kernel_sigset_t sigset(set); +int sigwait(const sigset_t* bionic_set, int* sig) { + SigSetConverter set = {}; + set.sigset = *bionic_set; + return sigwait64(&set.sigset64, sig); +} + +int sigwait64(const sigset64_t* set, int* sig) { while (true) { // __rt_sigtimedwait can return EAGAIN or EINTR, we need to loop // around them since sigwait is only allowed to return EINVAL. - int result = __rt_sigtimedwait(sigset.get(), NULL, NULL, sizeof(sigset)); + int result = sigtimedwait64(set, nullptr, nullptr); if (result >= 0) { *sig = result; return 0; } - - if (errno != EAGAIN && errno != EINTR) { - return errno; - } + if (errno != EAGAIN && errno != EINTR) return errno; } } int sigwaitinfo(const sigset_t* set, siginfo_t* info) { - return sigtimedwait(set, info, NULL); + return sigtimedwait(set, info, nullptr); +} + +int sigwaitinfo64(const sigset64_t* set, siginfo_t* info) { + return sigtimedwait64(set, info, nullptr); } diff --git a/libc/bionic/spawn.cpp b/libc/bionic/spawn.cpp index e5075f54e..7422a0bb4 100644 --- a/libc/bionic/spawn.cpp +++ b/libc/bionic/spawn.cpp @@ -36,6 +36,7 @@ #include <unistd.h> #include "private/ScopedSignalBlocker.h" +#include "private/SigSetConverter.h" enum Action { kOpen, @@ -87,8 +88,8 @@ struct __posix_spawnattr { pid_t pgroup; sched_param schedparam; int schedpolicy; - sigset_t sigmask; - sigset_t sigdefault; + SigSetConverter sigmask; + SigSetConverter sigdefault; }; static void ApplyAttrs(short flags, const posix_spawnattr_t* attr) { @@ -100,7 +101,7 @@ static void ApplyAttrs(short flags, const posix_spawnattr_t* attr) { const struct sigaction default_sa = { .sa_handler = SIG_DFL }; for (int s = 1; s < _NSIG; ++s) { bool reset = false; - if (use_sigdefault && sigismember(&(*attr)->sigdefault, s)) { + if (use_sigdefault && sigismember64(&(*attr)->sigdefault.sigset64, s)) { reset = true; } else { struct sigaction current; @@ -126,7 +127,7 @@ static void ApplyAttrs(short flags, const posix_spawnattr_t* attr) { } if ((flags & POSIX_SPAWN_SETSIGMASK) != 0) { - if (sigprocmask(SIG_SETMASK, &(*attr)->sigmask, nullptr)) _exit(127); + if (sigprocmask64(SIG_SETMASK, &(*attr)->sigmask.sigset64, nullptr)) _exit(127); } } @@ -209,22 +210,42 @@ int posix_spawnattr_getpgroup(const posix_spawnattr_t* attr, pid_t* pgroup) { } int posix_spawnattr_setsigmask(posix_spawnattr_t* attr, const sigset_t* mask) { - (*attr)->sigmask = *mask; + (*attr)->sigmask.sigset = *mask; + return 0; +} + +int posix_spawnattr_setsigmask64(posix_spawnattr_t* attr, const sigset64_t* mask) { + (*attr)->sigmask.sigset64 = *mask; return 0; } int posix_spawnattr_getsigmask(const posix_spawnattr_t* attr, sigset_t* mask) { - *mask = (*attr)->sigmask; + *mask = (*attr)->sigmask.sigset; + return 0; +} + +int posix_spawnattr_getsigmask64(const posix_spawnattr_t* attr, sigset64_t* mask) { + *mask = (*attr)->sigmask.sigset64; return 0; } int posix_spawnattr_setsigdefault(posix_spawnattr_t* attr, const sigset_t* mask) { - (*attr)->sigdefault = *mask; + (*attr)->sigdefault.sigset = *mask; + return 0; +} + +int posix_spawnattr_setsigdefault64(posix_spawnattr_t* attr, const sigset64_t* mask) { + (*attr)->sigdefault.sigset64 = *mask; return 0; } int posix_spawnattr_getsigdefault(const posix_spawnattr_t* attr, sigset_t* mask) { - *mask = (*attr)->sigdefault; + *mask = (*attr)->sigdefault.sigset; + return 0; +} + +int posix_spawnattr_getsigdefault64(const posix_spawnattr_t* attr, sigset64_t* mask) { + *mask = (*attr)->sigdefault.sigset64; return 0; } diff --git a/libc/bionic/epoll_pwait.cpp b/libc/bionic/sys_epoll.cpp index f3af93ef2..9f829127f 100644 --- a/libc/bionic/epoll_pwait.cpp +++ b/libc/bionic/sys_epoll.cpp @@ -26,18 +26,36 @@ * SUCH DAMAGE. */ +#include <errno.h> #include <sys/epoll.h> -#include "private/kernel_sigset_t.h" +#include "private/SigSetConverter.h" -extern "C" int __epoll_pwait(int, epoll_event*, int, int, const kernel_sigset_t*, size_t); +extern "C" int __epoll_pwait(int, epoll_event*, int, int, const sigset64_t*, size_t); + +int epoll_create(int size) { + if (size <= 0) { + errno = EINVAL; + return -1; + } + return epoll_create1(0); +} int epoll_pwait(int fd, epoll_event* events, int max_events, int timeout, const sigset_t* ss) { - kernel_sigset_t kernel_ss; - kernel_sigset_t* kernel_ss_ptr = NULL; - if (ss != NULL) { - kernel_ss.set(ss); - kernel_ss_ptr = &kernel_ss; + SigSetConverter set; + sigset64_t* ss_ptr = nullptr; + if (ss != nullptr) { + set = {}; + set.sigset = *ss; + ss_ptr = &set.sigset64; } - return __epoll_pwait(fd, events, max_events, timeout, kernel_ss_ptr, sizeof(kernel_ss)); + return epoll_pwait64(fd, events, max_events, timeout, ss_ptr); +} + +int epoll_pwait64(int fd, epoll_event* events, int max_events, int timeout, const sigset64_t* ss) { + return __epoll_pwait(fd, events, max_events, timeout, ss, sizeof(*ss)); +} + +int epoll_wait(int fd, struct epoll_event* events, int max_events, int timeout) { + return epoll_pwait64(fd, events, max_events, timeout, nullptr); } diff --git a/libc/bionic/sys_signalfd.cpp b/libc/bionic/sys_signalfd.cpp index 63e1db431..53d1f25c9 100644 --- a/libc/bionic/sys_signalfd.cpp +++ b/libc/bionic/sys_signalfd.cpp @@ -28,11 +28,16 @@ #include <sys/signalfd.h> -#include "private/kernel_sigset_t.h" +#include "private/SigSetConverter.h" -extern "C" int __signalfd4(int fd, kernel_sigset_t* mask, size_t sizemask, int flags); +extern "C" int __signalfd4(int, const sigset64_t*, size_t, int); int signalfd(int fd, const sigset_t* mask, int flags) { - kernel_sigset_t in_set(mask); - return __signalfd4(fd, &in_set, sizeof(in_set), flags); + SigSetConverter set = {}; + set.sigset = *mask; + return signalfd64(fd, &set.sigset64, flags); +} + +int signalfd64(int fd, const sigset64_t* mask, int flags) { + return __signalfd4(fd, mask, sizeof(*mask), flags); } diff --git a/libc/include/poll.h b/libc/include/poll.h index 8517dc623..9ca1cf8e4 100644 --- a/libc/include/poll.h +++ b/libc/include/poll.h @@ -40,6 +40,7 @@ typedef unsigned int nfds_t; int poll(struct pollfd* __fds, nfds_t __count, int __timeout_ms) __overloadable __RENAME_CLANG(poll); int ppoll(struct pollfd* __fds, nfds_t __count, const struct timespec* __timeout, const sigset_t* __mask) __overloadable __RENAME_CLANG(ppoll) __INTRODUCED_IN(21); +int ppoll64(struct pollfd* __fds, nfds_t __count, const struct timespec* __timeout, const sigset64_t* __mask) __INTRODUCED_IN(28); #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS) #include <bits/fortify/poll.h> diff --git a/libc/include/signal.h b/libc/include/signal.h index d9c9ee246..61bb395fa 100644 --- a/libc/include/signal.h +++ b/libc/include/signal.h @@ -80,6 +80,13 @@ typedef __sighandler_t sighandler_t; /* glibc compatibility. */ #define si_timerid si_tid /* glibc compatibility. */ +/* sigset_t is already large enough on LP64, but LP32's sigset_t is just `unsigned long`. */ +#if defined(__LP64__) +typedef sigset_t sigset64_t; +#else +typedef struct { unsigned long __bits[_KERNEL__NSIG/LONG_BIT]; } sigset64_t; +#endif + #if defined(__LP64__) struct sigaction { @@ -117,6 +124,7 @@ struct sigaction { #endif +// TODO: sigaction contains a sigset_t that's too small on LP32. int sigaction(int __signal, const struct sigaction* __new_action, struct sigaction* __old_action); int siginterrupt(int __signal, int __flag); @@ -124,18 +132,27 @@ int siginterrupt(int __signal, int __flag); #if __ANDROID_API__ >= __ANDROID_API_L__ sighandler_t signal(int __signal, sighandler_t __handler) __INTRODUCED_IN(21); int sigaddset(sigset_t* __set, int __signal) __INTRODUCED_IN(21); +int sigaddset64(sigset64_t* __set, int __signal) __INTRODUCED_IN(28); int sigdelset(sigset_t* __set, int __signal) __INTRODUCED_IN(21); +int sigdelset64(sigset64_t* __set, int __signal) __INTRODUCED_IN(28); int sigemptyset(sigset_t* __set) __INTRODUCED_IN(21); +int sigemptyset64(sigset64_t* __set) __INTRODUCED_IN(28); int sigfillset(sigset_t* __set) __INTRODUCED_IN(21); +int sigfillset64(sigset64_t* __set) __INTRODUCED_IN(28); int sigismember(const sigset_t* __set, int __signal) __INTRODUCED_IN(21); +int sigismember64(const sigset64_t* __set, int __signal) __INTRODUCED_IN(28); #else // Implemented as static inlines before 21. #endif int sigpending(sigset_t* __set); +int sigpending64(sigset64_t* __set) __INTRODUCED_IN(28); int sigprocmask(int __how, const sigset_t* __new_set, sigset_t* __old_set); +int sigprocmask64(int __how, const sigset64_t* __new_set, sigset64_t* __old_set) __INTRODUCED_IN(28); int sigsuspend(const sigset_t* __mask); +int sigsuspend64(const sigset64_t* __mask) __INTRODUCED_IN(28); int sigwait(const sigset_t* __set, int* __signal); +int sigwait64(const sigset64_t* __set, int* __signal) __INTRODUCED_IN(28); int sighold(int __signal) __attribute__((deprecated("use sigprocmask() or pthread_sigmask() instead"))) @@ -162,10 +179,13 @@ void psignal(int __signal, const char* __msg) __INTRODUCED_IN(17); int pthread_kill(pthread_t __pthread, int __signal); 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); int sigqueue(pid_t __pid, int __signal, const union sigval __value) __INTRODUCED_IN(23); int sigtimedwait(const sigset_t* __set, siginfo_t* __info, const struct timespec* __timeout) __INTRODUCED_IN(23); +int sigtimedwait64(const sigset64_t* __set, siginfo_t* __info, const struct timespec* __timeout) __INTRODUCED_IN(28); int sigwaitinfo(const sigset_t* __set, siginfo_t* __info) __INTRODUCED_IN(23); +int sigwaitinfo64(const sigset64_t* __set, siginfo_t* __info) __INTRODUCED_IN(28); __END_DECLS diff --git a/libc/include/spawn.h b/libc/include/spawn.h index b5ac58652..2e239bfc2 100644 --- a/libc/include/spawn.h +++ b/libc/include/spawn.h @@ -63,10 +63,14 @@ int posix_spawnattr_setpgroup(posix_spawnattr_t* __attr, pid_t __pgroup) __INTRO int posix_spawnattr_getpgroup(const posix_spawnattr_t* __attr, pid_t* __pgroup) __INTRODUCED_IN(28); int posix_spawnattr_setsigmask(posix_spawnattr_t* __attr, const sigset_t* __mask) __INTRODUCED_IN(28); +int posix_spawnattr_setsigmask64(posix_spawnattr_t* __attr, const sigset64_t* __mask) __INTRODUCED_IN(28); int posix_spawnattr_getsigmask(const posix_spawnattr_t* __attr, sigset_t* __mask) __INTRODUCED_IN(28); +int posix_spawnattr_getsigmask64(const posix_spawnattr_t* __attr, sigset64_t* __mask) __INTRODUCED_IN(28); int posix_spawnattr_setsigdefault(posix_spawnattr_t* __attr, const sigset_t* __mask) __INTRODUCED_IN(28); +int posix_spawnattr_setsigdefault64(posix_spawnattr_t* __attr, const sigset64_t* __mask) __INTRODUCED_IN(28); int posix_spawnattr_getsigdefault(const posix_spawnattr_t* __attr, sigset_t* __mask) __INTRODUCED_IN(28); +int posix_spawnattr_getsigdefault64(const posix_spawnattr_t* __attr, sigset64_t* __mask) __INTRODUCED_IN(28); int posix_spawnattr_setschedparam(posix_spawnattr_t* __attr, const struct sched_param* __param) __INTRODUCED_IN(28); int posix_spawnattr_getschedparam(const posix_spawnattr_t* __attr, struct sched_param* __param) __INTRODUCED_IN(28); diff --git a/libc/include/sys/epoll.h b/libc/include/sys/epoll.h index 2bc16f5b8..a213a90fb 100644 --- a/libc/include/sys/epoll.h +++ b/libc/include/sys/epoll.h @@ -58,6 +58,7 @@ int epoll_create1(int __flags) __INTRODUCED_IN(21); int epoll_ctl(int __epoll_fd, int __op, int __fd, struct epoll_event* __event); int epoll_wait(int __epoll_fd, struct epoll_event* __events, int __event_count, int __timeout_ms); int epoll_pwait(int __epoll_fd, struct epoll_event* __events, int __event_count, int __timeout_ms, const sigset_t* __mask) __INTRODUCED_IN(21); +int epoll_pwait64(int __epoll_fd, struct epoll_event* __events, int __event_count, int __timeout_ms, const sigset64_t* __mask) __INTRODUCED_IN(28); __END_DECLS diff --git a/libc/include/sys/select.h b/libc/include/sys/select.h index ac51d3fc8..603a5a676 100644 --- a/libc/include/sys/select.h +++ b/libc/include/sys/select.h @@ -75,6 +75,7 @@ int __FD_ISSET_chk(int, const fd_set*, size_t) __INTRODUCED_IN(21); int select(int __fd_count, fd_set* __read_fds, fd_set* __write_fds, fd_set* __exception_fds, struct timeval* __timeout); int pselect(int __fd_count, fd_set* __read_fds, fd_set* __write_fds, fd_set* __exception_fds, const struct timespec* __timeout, const sigset_t* __mask); +int pselect64(int __fd_count, fd_set* __read_fds, fd_set* __write_fds, fd_set* __exception_fds, const struct timespec* __timeout, const sigset64_t* __mask); __END_DECLS diff --git a/libc/include/sys/signalfd.h b/libc/include/sys/signalfd.h index 315622c7f..2337cd773 100644 --- a/libc/include/sys/signalfd.h +++ b/libc/include/sys/signalfd.h @@ -37,6 +37,7 @@ __BEGIN_DECLS int signalfd(int __fd, const sigset_t* __mask, int __flags) __INTRODUCED_IN(18); +int signalfd64(int __fd, const sigset64_t* __mask, int __flags) __INTRODUCED_IN(28); __END_DECLS diff --git a/libc/libc.arm.map b/libc/libc.arm.map index 1ed4ec6e8..c345ba636 100644 --- a/libc/libc.arm.map +++ b/libc/libc.arm.map @@ -1325,6 +1325,7 @@ LIBC_P { # introduced=P endhostent; endnetent; endprotoent; + epoll_pwait64; fexecve; fflush_unlocked; fgetc_unlocked; @@ -1356,28 +1357,47 @@ LIBC_P { # introduced=P posix_spawnattr_getschedparam; posix_spawnattr_getschedpolicy; posix_spawnattr_getsigdefault; + posix_spawnattr_getsigdefault64; posix_spawnattr_getsigmask; + posix_spawnattr_getsigmask64; posix_spawnattr_init; posix_spawnattr_setflags; posix_spawnattr_setpgroup; posix_spawnattr_setschedparam; posix_spawnattr_setschedpolicy; posix_spawnattr_setsigdefault; + posix_spawnattr_setsigdefault64; posix_spawnattr_setsigmask; + posix_spawnattr_setsigmask64; posix_spawn_file_actions_addclose; posix_spawn_file_actions_adddup2; posix_spawn_file_actions_addopen; posix_spawn_file_actions_destroy; posix_spawn_file_actions_init; posix_spawnp; + ppoll64; + pselect64; pthread_attr_getinheritsched; pthread_attr_setinheritsched; pthread_mutexattr_getprotocol; pthread_mutexattr_setprotocol; pthread_setschedprio; + pthread_sigmask64; sethostent; setnetent; setprotoent; + sigaddset64; + sigdelset64; + sigemptyset64; + sigfillset64; + sigismember64; + signalfd64; + sigpending64; + sigprocmask64; + sigsuspend64; + sigtimedwait64; + sigwait64; + sigwaitinfo64; swab; syncfs; } LIBC_O; diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map index f5117077b..3af0d423b 100644 --- a/libc/libc.arm64.map +++ b/libc/libc.arm64.map @@ -1245,6 +1245,7 @@ LIBC_P { # introduced=P endhostent; endnetent; endprotoent; + epoll_pwait64; fexecve; fflush_unlocked; fgetc_unlocked; @@ -1276,28 +1277,47 @@ LIBC_P { # introduced=P posix_spawnattr_getschedparam; posix_spawnattr_getschedpolicy; posix_spawnattr_getsigdefault; + posix_spawnattr_getsigdefault64; posix_spawnattr_getsigmask; + posix_spawnattr_getsigmask64; posix_spawnattr_init; posix_spawnattr_setflags; posix_spawnattr_setpgroup; posix_spawnattr_setschedparam; posix_spawnattr_setschedpolicy; posix_spawnattr_setsigdefault; + posix_spawnattr_setsigdefault64; posix_spawnattr_setsigmask; + posix_spawnattr_setsigmask64; posix_spawn_file_actions_addclose; posix_spawn_file_actions_adddup2; posix_spawn_file_actions_addopen; posix_spawn_file_actions_destroy; posix_spawn_file_actions_init; posix_spawnp; + ppoll64; + pselect64; pthread_attr_getinheritsched; pthread_attr_setinheritsched; pthread_mutexattr_getprotocol; pthread_mutexattr_setprotocol; pthread_setschedprio; + pthread_sigmask64; sethostent; setnetent; setprotoent; + sigaddset64; + sigdelset64; + sigemptyset64; + sigfillset64; + sigismember64; + signalfd64; + sigpending64; + sigprocmask64; + sigsuspend64; + sigtimedwait64; + sigwait64; + sigwaitinfo64; swab; syncfs; } LIBC_O; diff --git a/libc/libc.map.txt b/libc/libc.map.txt index 09605607a..5c54ba105 100644 --- a/libc/libc.map.txt +++ b/libc/libc.map.txt @@ -1350,6 +1350,7 @@ LIBC_P { # introduced=P endhostent; endnetent; endprotoent; + epoll_pwait64; fexecve; fflush_unlocked; fgetc_unlocked; @@ -1381,28 +1382,47 @@ LIBC_P { # introduced=P posix_spawnattr_getschedparam; posix_spawnattr_getschedpolicy; posix_spawnattr_getsigdefault; + posix_spawnattr_getsigdefault64; posix_spawnattr_getsigmask; + posix_spawnattr_getsigmask64; posix_spawnattr_init; posix_spawnattr_setflags; posix_spawnattr_setpgroup; posix_spawnattr_setschedparam; posix_spawnattr_setschedpolicy; posix_spawnattr_setsigdefault; + posix_spawnattr_setsigdefault64; posix_spawnattr_setsigmask; + posix_spawnattr_setsigmask64; posix_spawn_file_actions_addclose; posix_spawn_file_actions_adddup2; posix_spawn_file_actions_addopen; posix_spawn_file_actions_destroy; posix_spawn_file_actions_init; posix_spawnp; + ppoll64; + pselect64; pthread_attr_getinheritsched; pthread_attr_setinheritsched; pthread_mutexattr_getprotocol; pthread_mutexattr_setprotocol; pthread_setschedprio; + pthread_sigmask64; sethostent; setnetent; setprotoent; + sigaddset64; + sigdelset64; + sigemptyset64; + sigfillset64; + sigismember64; + signalfd64; + sigpending64; + sigprocmask64; + sigsuspend64; + sigtimedwait64; + sigwait64; + sigwaitinfo64; swab; syncfs; } LIBC_O; diff --git a/libc/libc.mips.map b/libc/libc.mips.map index 1160f8783..c3646085d 100644 --- a/libc/libc.mips.map +++ b/libc/libc.mips.map @@ -1309,6 +1309,7 @@ LIBC_P { # introduced=P endhostent; endnetent; endprotoent; + epoll_pwait64; fexecve; fflush_unlocked; fgetc_unlocked; @@ -1340,28 +1341,47 @@ LIBC_P { # introduced=P posix_spawnattr_getschedparam; posix_spawnattr_getschedpolicy; posix_spawnattr_getsigdefault; + posix_spawnattr_getsigdefault64; posix_spawnattr_getsigmask; + posix_spawnattr_getsigmask64; posix_spawnattr_init; posix_spawnattr_setflags; posix_spawnattr_setpgroup; posix_spawnattr_setschedparam; posix_spawnattr_setschedpolicy; posix_spawnattr_setsigdefault; + posix_spawnattr_setsigdefault64; posix_spawnattr_setsigmask; + posix_spawnattr_setsigmask64; posix_spawn_file_actions_addclose; posix_spawn_file_actions_adddup2; posix_spawn_file_actions_addopen; posix_spawn_file_actions_destroy; posix_spawn_file_actions_init; posix_spawnp; + ppoll64; + pselect64; pthread_attr_getinheritsched; pthread_attr_setinheritsched; pthread_mutexattr_getprotocol; pthread_mutexattr_setprotocol; pthread_setschedprio; + pthread_sigmask64; sethostent; setnetent; setprotoent; + sigaddset64; + sigdelset64; + sigemptyset64; + sigfillset64; + sigismember64; + signalfd64; + sigpending64; + sigprocmask64; + sigsuspend64; + sigtimedwait64; + sigwait64; + sigwaitinfo64; swab; syncfs; } LIBC_O; diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map index f5117077b..3af0d423b 100644 --- a/libc/libc.mips64.map +++ b/libc/libc.mips64.map @@ -1245,6 +1245,7 @@ LIBC_P { # introduced=P endhostent; endnetent; endprotoent; + epoll_pwait64; fexecve; fflush_unlocked; fgetc_unlocked; @@ -1276,28 +1277,47 @@ LIBC_P { # introduced=P posix_spawnattr_getschedparam; posix_spawnattr_getschedpolicy; posix_spawnattr_getsigdefault; + posix_spawnattr_getsigdefault64; posix_spawnattr_getsigmask; + posix_spawnattr_getsigmask64; posix_spawnattr_init; posix_spawnattr_setflags; posix_spawnattr_setpgroup; posix_spawnattr_setschedparam; posix_spawnattr_setschedpolicy; posix_spawnattr_setsigdefault; + posix_spawnattr_setsigdefault64; posix_spawnattr_setsigmask; + posix_spawnattr_setsigmask64; posix_spawn_file_actions_addclose; posix_spawn_file_actions_adddup2; posix_spawn_file_actions_addopen; posix_spawn_file_actions_destroy; posix_spawn_file_actions_init; posix_spawnp; + ppoll64; + pselect64; pthread_attr_getinheritsched; pthread_attr_setinheritsched; pthread_mutexattr_getprotocol; pthread_mutexattr_setprotocol; pthread_setschedprio; + pthread_sigmask64; sethostent; setnetent; setprotoent; + sigaddset64; + sigdelset64; + sigemptyset64; + sigfillset64; + sigismember64; + signalfd64; + sigpending64; + sigprocmask64; + sigsuspend64; + sigtimedwait64; + sigwait64; + sigwaitinfo64; swab; syncfs; } LIBC_O; diff --git a/libc/libc.x86.map b/libc/libc.x86.map index b0b4b162b..eec2c19cb 100644 --- a/libc/libc.x86.map +++ b/libc/libc.x86.map @@ -1307,6 +1307,7 @@ LIBC_P { # introduced=P endhostent; endnetent; endprotoent; + epoll_pwait64; fexecve; fflush_unlocked; fgetc_unlocked; @@ -1338,28 +1339,47 @@ LIBC_P { # introduced=P posix_spawnattr_getschedparam; posix_spawnattr_getschedpolicy; posix_spawnattr_getsigdefault; + posix_spawnattr_getsigdefault64; posix_spawnattr_getsigmask; + posix_spawnattr_getsigmask64; posix_spawnattr_init; posix_spawnattr_setflags; posix_spawnattr_setpgroup; posix_spawnattr_setschedparam; posix_spawnattr_setschedpolicy; posix_spawnattr_setsigdefault; + posix_spawnattr_setsigdefault64; posix_spawnattr_setsigmask; + posix_spawnattr_setsigmask64; posix_spawn_file_actions_addclose; posix_spawn_file_actions_adddup2; posix_spawn_file_actions_addopen; posix_spawn_file_actions_destroy; posix_spawn_file_actions_init; posix_spawnp; + ppoll64; + pselect64; pthread_attr_getinheritsched; pthread_attr_setinheritsched; pthread_mutexattr_getprotocol; pthread_mutexattr_setprotocol; pthread_setschedprio; + pthread_sigmask64; sethostent; setnetent; setprotoent; + sigaddset64; + sigdelset64; + sigemptyset64; + sigfillset64; + sigismember64; + signalfd64; + sigpending64; + sigprocmask64; + sigsuspend64; + sigtimedwait64; + sigwait64; + sigwaitinfo64; swab; syncfs; } LIBC_O; diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map index f5117077b..3af0d423b 100644 --- a/libc/libc.x86_64.map +++ b/libc/libc.x86_64.map @@ -1245,6 +1245,7 @@ LIBC_P { # introduced=P endhostent; endnetent; endprotoent; + epoll_pwait64; fexecve; fflush_unlocked; fgetc_unlocked; @@ -1276,28 +1277,47 @@ LIBC_P { # introduced=P posix_spawnattr_getschedparam; posix_spawnattr_getschedpolicy; posix_spawnattr_getsigdefault; + posix_spawnattr_getsigdefault64; posix_spawnattr_getsigmask; + posix_spawnattr_getsigmask64; posix_spawnattr_init; posix_spawnattr_setflags; posix_spawnattr_setpgroup; posix_spawnattr_setschedparam; posix_spawnattr_setschedpolicy; posix_spawnattr_setsigdefault; + posix_spawnattr_setsigdefault64; posix_spawnattr_setsigmask; + posix_spawnattr_setsigmask64; posix_spawn_file_actions_addclose; posix_spawn_file_actions_adddup2; posix_spawn_file_actions_addopen; posix_spawn_file_actions_destroy; posix_spawn_file_actions_init; posix_spawnp; + ppoll64; + pselect64; pthread_attr_getinheritsched; pthread_attr_setinheritsched; pthread_mutexattr_getprotocol; pthread_mutexattr_setprotocol; pthread_setschedprio; + pthread_sigmask64; sethostent; setnetent; setprotoent; + sigaddset64; + sigdelset64; + sigemptyset64; + sigfillset64; + sigismember64; + signalfd64; + sigpending64; + sigprocmask64; + sigsuspend64; + sigtimedwait64; + sigwait64; + sigwaitinfo64; swab; syncfs; } LIBC_O; diff --git a/libc/private/ScopedSignalBlocker.h b/libc/private/ScopedSignalBlocker.h index c3ab30759..7582068ac 100644 --- a/libc/private/ScopedSignalBlocker.h +++ b/libc/private/ScopedSignalBlocker.h @@ -20,14 +20,13 @@ #include <signal.h> #include "bionic_macros.h" -#include "kernel_sigset_t.h" class ScopedSignalBlocker { public: explicit ScopedSignalBlocker() { - kernel_sigset_t set; - set.fill(); - __rt_sigprocmask(SIG_SETMASK, &set, &old_set_, sizeof(set)); + sigset64_t set; + sigfillset64(&set); + sigprocmask64(SIG_SETMASK, &set, &old_set_); } ~ScopedSignalBlocker() { @@ -35,11 +34,11 @@ class ScopedSignalBlocker { } void reset() { - __rt_sigprocmask(SIG_SETMASK, &old_set_, nullptr, sizeof(old_set_)); + sigprocmask64(SIG_SETMASK, &old_set_, nullptr); } private: - kernel_sigset_t old_set_; + sigset64_t old_set_; DISALLOW_COPY_AND_ASSIGN(ScopedSignalBlocker); }; diff --git a/libc/bionic/epoll_create.cpp b/libc/private/SigSetConverter.h index 74f664f86..7d0b21573 100644 --- a/libc/bionic/epoll_create.cpp +++ b/libc/private/SigSetConverter.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2018 The Android Open Source Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +26,10 @@ * SUCH DAMAGE. */ -#include <errno.h> -#include <sys/epoll.h> +#pragma once -int epoll_create(int size) { - if (size <= 0) { - errno = EINVAL; - return -1; - } - return epoll_create1(0); -} +union SigSetConverter { + int bsd; + sigset_t sigset; + sigset64_t sigset64; +}; diff --git a/libc/private/kernel_sigset_t.h b/libc/private/kernel_sigset_t.h deleted file mode 100644 index bdfb729c6..000000000 --- a/libc/private/kernel_sigset_t.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LIBC_PRIVATE_KERNEL_SIGSET_T_H_ -#define LIBC_PRIVATE_KERNEL_SIGSET_T_H_ - -#include <errno.h> -#include <signal.h> - -#include <async_safe/log.h> - -// Our sigset_t is wrong for ARM and x86. It's 32-bit but the kernel expects 64 bits. -// This means we can't support real-time signals correctly without breaking the ABI. -// In the meantime, we can use this union to pass an appropriately-sized block of memory -// to the kernel, at the cost of not being able to refer to real-time signals when -// initializing from a sigset_t on LP32. -union kernel_sigset_t { - public: - kernel_sigset_t() { - } - - explicit kernel_sigset_t(int signal_number) { - clear(); - if (!set(signal_number)) async_safe_fatal("kernel_sigset_t(%d)", signal_number); - } - - explicit kernel_sigset_t(const sigset_t* value) { - clear(); - set(value); - } - - void clear() { - __builtin_memset(this, 0, sizeof(*this)); - } - - bool clear(int signal_number) { - int bit = bit_of(signal_number); - if (bit == -1) return false; - bits[bit / LONG_BIT] &= ~(1UL << (bit % LONG_BIT)); - return true; - } - - void fill() { - __builtin_memset(this, 0xff, sizeof(*this)); - } - - bool is_set(int signal_number) { - int bit = bit_of(signal_number); - if (bit == -1) return false; - return ((bits[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1) == 1; - } - - bool set(int signal_number) { - int bit = bit_of(signal_number); - if (bit == -1) return false; - bits[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT); - return true; - } - - void set(const sigset_t* value) { - clear(); - bionic = *value; - } - - sigset_t* get() { - return &bionic; - } - - sigset_t bionic; - unsigned long bits[_KERNEL__NSIG/LONG_BIT]; - - private: - int bit_of(int signal_number) { - int bit = signal_number - 1; // Signal numbers start at 1, but bit positions start at 0. - if (bit < 0 || bit >= static_cast<int>(8*sizeof(*this))) { - errno = EINVAL; - return -1; - } - return bit; - } -}; - -extern "C" int __rt_sigpending(const kernel_sigset_t*, size_t); -extern "C" int __rt_sigprocmask(int, const kernel_sigset_t*, kernel_sigset_t*, size_t); -extern "C" int __rt_sigsuspend(const kernel_sigset_t*, size_t); - -#endif diff --git a/tests/Android.bp b/tests/Android.bp index 25377df9d..443fe8e62 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -140,6 +140,7 @@ cc_test_library { "sys_sem_test.cpp", "sys_sendfile_test.cpp", "sys_shm_test.cpp", + "sys_signalfd_test.cpp", "sys_socket_test.cpp", "sys_stat_test.cpp", "sys_statvfs_test.cpp", diff --git a/tests/ScopedSignalHandler.h b/tests/ScopedSignalHandler.h index 71f22dce7..85c41a87c 100644 --- a/tests/ScopedSignalHandler.h +++ b/tests/ScopedSignalHandler.h @@ -20,6 +20,26 @@ #include <signal.h> #include <string.h> +#if defined(__GLIBC__) +#define posix_spawnattr_getsigdefault64 posix_spawnattr_getsigdefault +#define posix_spawnattr_getsigmask64 posix_spawnattr_getsigmask +#define posix_spawnattr_setsigdefault64 posix_spawnattr_setsigdefault +#define posix_spawnattr_setsigmask64 posix_spawnattr_setsigmask +#define pthread_sigmask64 pthread_sigmask +#define sigaddset64 sigaddset +#define sigdelset64 sigdelset +#define sigemptyset64 sigemptyset +#define sigfillset64 sigfillset +#define sigismember64 sigismember +#define sigpending64 sigpending +#define sigprocmask64 sigprocmask +#define sigset64_t sigset_t +#define sigsuspend64 sigsuspend +#define sigtimedwait64 sigtimedwait +#define sigwait64 sigwait +#define sigwaitinfo64 sigwaitinfo +#endif + class ScopedSignalHandler { public: ScopedSignalHandler(int signal_number, void (*handler)(int), int sa_flags = 0) @@ -56,15 +76,15 @@ class ScopedSignalHandler { class SignalMaskRestorer { public: SignalMaskRestorer() { - sigprocmask(SIG_SETMASK, nullptr, &old_mask_); + sigprocmask64(SIG_SETMASK, nullptr, &old_mask_); } ~SignalMaskRestorer() { - sigprocmask(SIG_SETMASK, &old_mask_, nullptr); + sigprocmask64(SIG_SETMASK, &old_mask_, nullptr); } private: - sigset_t old_mask_; + sigset64_t old_mask_; }; #endif // _BIONIC_TESTS_SCOPED_SIGNAL_HANDLER_H diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp index 9ecb10cbc..f28861231 100644 --- a/tests/pthread_test.cpp +++ b/tests/pthread_test.cpp @@ -356,9 +356,9 @@ TEST_F(pthread_DeathTest, pthread_bug_37410) { } static void* SignalHandlerFn(void* arg) { - sigset_t wait_set; - sigfillset(&wait_set); - return reinterpret_cast<void*>(sigwait(&wait_set, reinterpret_cast<int*>(arg))); + sigset64_t wait_set; + sigfillset64(&wait_set); + return reinterpret_cast<void*>(sigwait64(&wait_set, reinterpret_cast<int*>(arg))); } TEST(pthread, pthread_sigmask) { @@ -402,6 +402,47 @@ TEST(pthread, pthread_sigmask) { ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &original_set, NULL)); } +TEST(pthread, pthread_sigmask64_SIGTRMIN) { + // Check that SIGRTMIN isn't blocked. + sigset64_t original_set; + sigemptyset64(&original_set); + ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, NULL, &original_set)); + ASSERT_FALSE(sigismember64(&original_set, SIGRTMIN)); + + // Block SIGRTMIN. + sigset64_t set; + sigemptyset64(&set); + sigaddset64(&set, SIGRTMIN); + ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, &set, NULL)); + + // Check that SIGRTMIN is blocked. + sigset64_t final_set; + sigemptyset64(&final_set); + ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, NULL, &final_set)); + ASSERT_TRUE(sigismember64(&final_set, SIGRTMIN)); + // ...and that sigprocmask64 agrees with pthread_sigmask64. + sigemptyset64(&final_set); + ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, NULL, &final_set)); + ASSERT_TRUE(sigismember64(&final_set, SIGRTMIN)); + + // Spawn a thread that calls sigwait64 and tells us what it received. + pthread_t signal_thread; + int received_signal = -1; + ASSERT_EQ(0, pthread_create(&signal_thread, NULL, SignalHandlerFn, &received_signal)); + + // Send that thread SIGRTMIN. + pthread_kill(signal_thread, SIGRTMIN); + + // See what it got. + void* join_result; + ASSERT_EQ(0, pthread_join(signal_thread, &join_result)); + ASSERT_EQ(SIGRTMIN, received_signal); + ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(join_result)); + + // Restore the original signal mask. + ASSERT_EQ(0, pthread_sigmask64(SIG_SETMASK, &original_set, NULL)); +} + static void test_pthread_setname_np__pthread_getname_np(pthread_t t) { ASSERT_EQ(0, pthread_setname_np(t, "short")); char name[32]; @@ -1378,18 +1419,23 @@ TEST(pthread, pthread_attr_getstack__main_thread) { EXPECT_EQ(stack_size, stack_size2); #if defined(__BIONIC__) - // What does /proc/self/maps' [stack] line say? + // Find stack in /proc/self/maps using a pointer to the stack. + // + // We do not use "[stack]" label because in native-bridge environment it is not + // guaranteed to point to the right stack. A native bridge implementation may + // keep separate stack for the guest code. void* maps_stack_hi = NULL; std::vector<map_record> maps; ASSERT_TRUE(Maps::parse_maps(&maps)); + uintptr_t stack_address = reinterpret_cast<uintptr_t>(&maps_stack_hi); for (const auto& map : maps) { - if (map.pathname == "[stack]") { + if (map.addr_start <= stack_address && map.addr_end > stack_address){ maps_stack_hi = reinterpret_cast<void*>(map.addr_end); break; } } - // The high address of the /proc/self/maps [stack] region should equal stack_base + stack_size. + // The high address of the /proc/self/maps stack region should equal stack_base + stack_size. // Remember that the stack grows down (and is mapped in on demand), so the low address of the // region isn't very interesting. EXPECT_EQ(maps_stack_hi, reinterpret_cast<uint8_t*>(stack_base) + stack_size); diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp index 5cbec883a..ebc079e1d 100644 --- a/tests/signal_test.cpp +++ b/tests/signal_test.cpp @@ -20,57 +20,45 @@ #include <sys/types.h> #include <unistd.h> +#include <thread> + #include <gtest/gtest.h> #include "ScopedSignalHandler.h" -static size_t SIGNAL_MIN() { +static int SIGNAL_MIN() { return 1; // Signals start at 1 (SIGHUP), not 0. } -static size_t SIGNAL_MAX() { - size_t result = SIGRTMAX; - -#if defined(__BIONIC__) && !defined(__mips__) && !defined(__LP64__) - // 32-bit bionic's sigset_t is too small for ARM and x86: 32 bits instead of 64. - // This means you can't refer to any of the real-time signals. - // See http://b/3038348 and http://b/5828899. - result = 32; -#else - // Otherwise, C libraries should be perfectly capable of using their largest signal. - if (sizeof(sigset_t) * 8 < static_cast<size_t>(SIGRTMAX)) { - abort(); - } -#endif - - return result; +template <typename SigSetT> +static int SIGNAL_MAX(SigSetT* set) { + return sizeof(*set) * 8; } -template <typename Fn> -static void TestSigSet1(Fn fn) { - // NULL sigset_t*. - sigset_t* set_ptr = NULL; +template <typename SigSetT> +static void TestSigSet1(int (fn)(SigSetT*)) { + // NULL sigset_t*/sigset64_t*. + SigSetT* set_ptr = NULL; errno = 0; ASSERT_EQ(-1, fn(set_ptr)); ASSERT_EQ(EINVAL, errno); // Non-NULL. - sigset_t set; + SigSetT set = {}; errno = 0; ASSERT_EQ(0, fn(&set)); ASSERT_EQ(0, errno); } -template <typename Fn> -static void TestSigSet2(Fn fn) { - // NULL sigset_t*. - sigset_t* set_ptr = NULL; +template <typename SigSetT> +static void TestSigSet2(int (fn)(SigSetT*, int)) { + // NULL sigset_t*/sigset64_t*. + SigSetT* set_ptr = NULL; errno = 0; ASSERT_EQ(-1, fn(set_ptr, SIGSEGV)); ASSERT_EQ(EINVAL, errno); - sigset_t set; - sigemptyset(&set); + SigSetT set = {}; // Bad signal number: too small. errno = 0; @@ -79,37 +67,67 @@ static void TestSigSet2(Fn fn) { // Bad signal number: too high. errno = 0; - ASSERT_EQ(-1, fn(&set, SIGNAL_MAX() + 1)); + ASSERT_EQ(-1, fn(&set, SIGNAL_MAX(&set) + 1)); ASSERT_EQ(EINVAL, errno); // Good signal numbers, low and high ends of range. errno = 0; ASSERT_EQ(0, fn(&set, SIGNAL_MIN())); ASSERT_EQ(0, errno); - ASSERT_EQ(0, fn(&set, SIGNAL_MAX())); + ASSERT_EQ(0, fn(&set, SIGNAL_MAX(&set))); ASSERT_EQ(0, errno); } -TEST(signal, sigismember_invalid) { - TestSigSet2(sigismember); -} - TEST(signal, sigaddset_invalid) { TestSigSet2(sigaddset); } +TEST(signal, sigaddset64_invalid) { +#if defined(__BIONIC__) + TestSigSet2(sigaddset64); +#endif +} + TEST(signal, sigdelset_invalid) { TestSigSet2(sigdelset); } +TEST(signal, sigdelset64_invalid) { +#if defined(__BIONIC__) + TestSigSet2(sigdelset64); +#endif +} + TEST(signal, sigemptyset_invalid) { TestSigSet1(sigemptyset); } +TEST(signal, sigemptyset64_invalid) { +#if defined(__BIONIC__) + TestSigSet1(sigemptyset64); +#endif +} + TEST(signal, sigfillset_invalid) { TestSigSet1(sigfillset); } +TEST(signal, sigfillset64_invalid) { +#if defined(__BIONIC__) + TestSigSet1(sigfillset64); +#endif +} + +TEST(signal, sigismember_invalid) { + TestSigSet2(sigismember); +} + +TEST(signal, sigismember64_invalid) { +#if defined(__BIONIC__) + TestSigSet2(sigismember64); +#endif +} + TEST(signal, raise_invalid) { errno = 0; ASSERT_EQ(-1, raise(-1)); @@ -129,12 +147,8 @@ TEST(signal, raise_in_signal_handler) { raise(SIGALRM); } -static void HandleSIGALRM(int signal_number) { - ASSERT_EQ(SIGALRM, signal_number); -} - -TEST(signal, sigwait) { - ScopedSignalHandler ssh(SIGALRM, HandleSIGALRM); +TEST(signal, sigwait_SIGALRM) { + ScopedSignalHandler ssh(SIGALRM, [](int sig) { ASSERT_EQ(SIGALRM, sig); }); sigset_t wait_set; sigemptyset(&wait_set); @@ -149,38 +163,57 @@ TEST(signal, sigwait) { ASSERT_EQ(SIGALRM, received_signal); } -static int g_sigsuspend_test_helper_call_count = 0; +TEST(signal, sigwait64_SIGRTMIN) { + ScopedSignalHandler ssh(SIGRTMIN, [](int sig) { ASSERT_EQ(SIGRTMIN, sig); }); + + sigset64_t wait_set; + sigemptyset64(&wait_set); + sigaddset64(&wait_set, SIGRTMIN); + + pid_t pid = getpid(); + std::thread thread([&pid]() { + usleep(5000); + kill(pid, SIGRTMIN); + }); + + int received_signal; + errno = 0; + ASSERT_EQ(0, sigwait64(&wait_set, &received_signal)); + ASSERT_EQ(0, errno); + ASSERT_EQ(SIGRTMIN, received_signal); -static void SigSuspendTestHelper(int) { - ++g_sigsuspend_test_helper_call_count; + thread.join(); } +static int g_sigsuspend_signal_handler_call_count = 0; + TEST(signal, sigsuspend_sigpending) { + SignalMaskRestorer smr; + // Block SIGALRM. sigset_t just_SIGALRM; sigemptyset(&just_SIGALRM); sigaddset(&just_SIGALRM, SIGALRM); - sigset_t original_set; - ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); + ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr)); - ScopedSignalHandler ssh(SIGALRM, SigSuspendTestHelper); + ScopedSignalHandler ssh(SIGALRM, [](int) { ++g_sigsuspend_signal_handler_call_count; }); // There should be no pending signals. sigset_t pending; sigemptyset(&pending); ASSERT_EQ(0, sigpending(&pending)); - for (size_t i = SIGNAL_MIN(); i <= SIGNAL_MAX(); ++i) { + for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) { EXPECT_FALSE(sigismember(&pending, i)) << i; } // Raise SIGALRM and check our signal handler wasn't called. raise(SIGALRM); - ASSERT_EQ(0, g_sigsuspend_test_helper_call_count); + ASSERT_EQ(0, g_sigsuspend_signal_handler_call_count); // We should now have a pending SIGALRM but nothing else. sigemptyset(&pending); ASSERT_EQ(0, sigpending(&pending)); - for (size_t i = SIGNAL_MIN(); i <= SIGNAL_MAX(); ++i) { + for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) { EXPECT_EQ((i == SIGALRM), sigismember(&pending, i)); } @@ -191,10 +224,49 @@ TEST(signal, sigsuspend_sigpending) { ASSERT_EQ(-1, sigsuspend(¬_SIGALRM)); ASSERT_EQ(EINTR, errno); // ...and check that we now receive our pending SIGALRM. - ASSERT_EQ(1, g_sigsuspend_test_helper_call_count); + ASSERT_EQ(1, g_sigsuspend_signal_handler_call_count); +} - // Restore the original set. - ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL)); +static int g_sigsuspend64_signal_handler_call_count = 0; + +TEST(signal, sigsuspend64_sigpending64) { + SignalMaskRestorer smr; + + // Block SIGRTMIN. + sigset64_t just_SIGRTMIN; + sigemptyset64(&just_SIGRTMIN); + sigaddset64(&just_SIGRTMIN, SIGRTMIN); + ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr)); + + ScopedSignalHandler ssh(SIGRTMIN, [](int) { ++g_sigsuspend64_signal_handler_call_count; }); + + // There should be no pending signals. + sigset64_t pending; + sigemptyset64(&pending); + ASSERT_EQ(0, sigpending64(&pending)); + for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) { + EXPECT_FALSE(sigismember64(&pending, i)) << i; + } + + // Raise SIGRTMIN and check our signal handler wasn't called. + raise(SIGRTMIN); + ASSERT_EQ(0, g_sigsuspend64_signal_handler_call_count); + + // We should now have a pending SIGRTMIN but nothing else. + sigemptyset64(&pending); + ASSERT_EQ(0, sigpending64(&pending)); + for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) { + EXPECT_EQ((i == SIGRTMIN), sigismember64(&pending, i)); + } + + // Use sigsuspend64 to block everything except SIGRTMIN... + sigset64_t not_SIGRTMIN; + sigfillset64(¬_SIGRTMIN); + sigdelset64(¬_SIGRTMIN, SIGRTMIN); + ASSERT_EQ(-1, sigsuspend64(¬_SIGRTMIN)); + ASSERT_EQ(EINTR, errno); + // ...and check that we now receive our pending SIGRTMIN. + ASSERT_EQ(1, g_sigsuspend64_signal_handler_call_count); } static void EmptySignalHandler(int) {} @@ -301,12 +373,13 @@ TEST(signal, sigqueue) { } TEST(signal, sigwaitinfo) { + SignalMaskRestorer smr; + // Block SIGALRM. sigset_t just_SIGALRM; sigemptyset(&just_SIGALRM); sigaddset(&just_SIGALRM, SIGALRM); - sigset_t original_set; - ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); + ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr)); // Raise SIGALRM. sigval_t sigval; @@ -320,38 +393,75 @@ TEST(signal, sigwaitinfo) { ASSERT_EQ(0, errno); ASSERT_EQ(SIGALRM, info.si_signo); ASSERT_EQ(1, info.si_value.sival_int); +} - ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL)); +TEST(signal, sigwaitinfo64_SIGRTMIN) { + SignalMaskRestorer smr; + + // Block SIGRTMIN. + sigset64_t just_SIGRTMIN; + sigemptyset64(&just_SIGRTMIN); + sigaddset64(&just_SIGRTMIN, SIGRTMIN); + ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr)); + + // Raise SIGRTMIN. + sigval_t sigval; + sigval.sival_int = 1; + ASSERT_EQ(0, sigqueue(getpid(), SIGRTMIN, sigval)); + + // Get pending SIGRTMIN. + siginfo_t info; + errno = 0; + ASSERT_EQ(SIGRTMIN, sigwaitinfo64(&just_SIGRTMIN, &info)); + ASSERT_EQ(0, errno); + ASSERT_EQ(SIGRTMIN, info.si_signo); + ASSERT_EQ(1, info.si_value.sival_int); } TEST(signal, sigtimedwait) { + SignalMaskRestorer smr; + // Block SIGALRM. sigset_t just_SIGALRM; sigemptyset(&just_SIGALRM); sigaddset(&just_SIGALRM, SIGALRM); - sigset_t original_set; - ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); + ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr)); // Raise SIGALRM. - sigval_t sigval; - sigval.sival_int = 1; + sigval_t sigval = { .sival_int = 1 }; ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval)); // Get pending SIGALRM. siginfo_t info; - struct timespec timeout; - timeout.tv_sec = 2; - timeout.tv_nsec = 0; + timespec timeout = { .tv_sec = 2, .tv_nsec = 0 }; errno = 0; ASSERT_EQ(SIGALRM, sigtimedwait(&just_SIGALRM, &info, &timeout)); ASSERT_EQ(0, errno); +} - ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL)); +TEST(signal, sigtimedwait64_SIGRTMIN) { + SignalMaskRestorer smr; + + // Block SIGRTMIN. + sigset64_t just_SIGRTMIN; + sigemptyset64(&just_SIGRTMIN); + sigaddset64(&just_SIGRTMIN, SIGRTMIN); + ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr)); + + // Raise SIGALRM. + sigval_t sigval = { .sival_int = 1 }; + ASSERT_EQ(0, sigqueue(getpid(), SIGRTMIN, sigval)); + + // Get pending SIGALRM. + siginfo_t info; + timespec timeout = { .tv_sec = 2, .tv_nsec = 0 }; + errno = 0; + ASSERT_EQ(SIGRTMIN, sigtimedwait64(&just_SIGRTMIN, &info, &timeout)); + ASSERT_EQ(0, errno); } static int64_t NanoTime() { - struct timespec t; - t.tv_sec = t.tv_nsec = 0; + timespec t; clock_gettime(CLOCK_MONOTONIC, &t); return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec; } @@ -367,9 +477,7 @@ TEST(signal, sigtimedwait_timeout) { // Wait timeout. int64_t start_time = NanoTime(); siginfo_t info; - struct timespec timeout; - timeout.tv_sec = 0; - timeout.tv_nsec = 1000000; + timespec timeout = { .tv_sec = 0, .tv_nsec = 1000000 }; errno = 0; ASSERT_EQ(-1, sigtimedwait(&just_SIGALRM, &info, &timeout)); ASSERT_EQ(EAGAIN, errno); @@ -411,17 +519,19 @@ TEST(signal, rt_tgsigqueueinfo) { << sent.si_code << ", received " << received.si_code << error_msg; } +#endif -#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__) TEST(signal, sigset_size) { // The setjmp implementations for ARM, AArch64, x86, and x86_64 assume that sigset_t can fit in a // long. This is true because ARM and x86 have broken rt signal support, and AArch64 and x86_64 // both have a SIGRTMAX defined as 64. +#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__) +#if defined(__BIONIC__) static_assert(sizeof(sigset_t) <= sizeof(long), "sigset_t doesn't fit in a long"); -} - #endif + static_assert(sizeof(sigset64_t)*8 >= 64, "sigset64_t too small for real-time signals"); #endif +} TEST(signal, sigignore_EINVAL) { errno = 0; diff --git a/tests/spawn_test.cpp b/tests/spawn_test.cpp index dfce0dc58..84df16d58 100644 --- a/tests/spawn_test.cpp +++ b/tests/spawn_test.cpp @@ -96,6 +96,25 @@ TEST(spawn, posix_spawnattr_setsigmask_posix_spawnattr_getsigmask) { ASSERT_EQ(0, posix_spawnattr_destroy(&sa)); } +TEST(spawn, posix_spawnattr_setsigmask64_posix_spawnattr_getsigmask64) { + posix_spawnattr_t sa; + ASSERT_EQ(0, posix_spawnattr_init(&sa)); + + sigset64_t sigs; + ASSERT_EQ(0, posix_spawnattr_getsigmask64(&sa, &sigs)); + ASSERT_FALSE(sigismember64(&sigs, SIGRTMIN)); + + sigset64_t just_SIGRTMIN; + sigemptyset64(&just_SIGRTMIN); + sigaddset64(&just_SIGRTMIN, SIGRTMIN); + ASSERT_EQ(0, posix_spawnattr_setsigmask64(&sa, &just_SIGRTMIN)); + + ASSERT_EQ(0, posix_spawnattr_getsigmask64(&sa, &sigs)); + ASSERT_TRUE(sigismember64(&sigs, SIGRTMIN)); + + ASSERT_EQ(0, posix_spawnattr_destroy(&sa)); +} + TEST(spawn, posix_spawnattr_setsigdefault_posix_spawnattr_getsigdefault) { posix_spawnattr_t sa; ASSERT_EQ(0, posix_spawnattr_init(&sa)); @@ -115,6 +134,25 @@ TEST(spawn, posix_spawnattr_setsigdefault_posix_spawnattr_getsigdefault) { ASSERT_EQ(0, posix_spawnattr_destroy(&sa)); } +TEST(spawn, posix_spawnattr_setsigdefault64_posix_spawnattr_getsigdefault64) { + posix_spawnattr_t sa; + ASSERT_EQ(0, posix_spawnattr_init(&sa)); + + sigset64_t sigs; + ASSERT_EQ(0, posix_spawnattr_getsigdefault64(&sa, &sigs)); + ASSERT_FALSE(sigismember64(&sigs, SIGRTMIN)); + + sigset64_t just_SIGRTMIN; + sigemptyset64(&just_SIGRTMIN); + sigaddset64(&just_SIGRTMIN, SIGRTMIN); + ASSERT_EQ(0, posix_spawnattr_setsigdefault64(&sa, &just_SIGRTMIN)); + + ASSERT_EQ(0, posix_spawnattr_getsigdefault64(&sa, &sigs)); + ASSERT_TRUE(sigismember64(&sigs, SIGRTMIN)); + + ASSERT_EQ(0, posix_spawnattr_destroy(&sa)); +} + TEST(spawn, posix_spawnattr_setsschedparam_posix_spawnattr_getsschedparam) { posix_spawnattr_t sa; ASSERT_EQ(0, posix_spawnattr_init(&sa)); diff --git a/tests/sys_epoll_test.cpp b/tests/sys_epoll_test.cpp index d1b411a27..7233ccc24 100644 --- a/tests/sys_epoll_test.cpp +++ b/tests/sys_epoll_test.cpp @@ -35,6 +35,11 @@ TEST(sys_epoll, smoke) { // epoll_pwait without a sigset (which is equivalent to epoll_wait). ASSERT_EQ(0, epoll_pwait(epoll_fd, events, 1, 1, NULL)); +#if defined(__BIONIC__) + // epoll_pwait64 without a sigset (which is equivalent to epoll_wait). + ASSERT_EQ(0, epoll_pwait64(epoll_fd, events, 1, 1, NULL)); +#endif + // epoll_pwait with a sigset. sigset_t ss; sigemptyset(&ss); diff --git a/libc/bionic/pthread_sigmask.cpp b/tests/sys_signalfd_test.cpp index 79f31a145..67a72e00f 100644 --- a/libc/bionic/pthread_sigmask.cpp +++ b/tests/sys_signalfd_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2018 The Android Open Source Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,14 +26,49 @@ * SUCH DAMAGE. */ +#include <gtest/gtest.h> + #include <errno.h> -#include <pthread.h> +#include <fcntl.h> #include <signal.h> +#include <sys/signalfd.h> +#include <unistd.h> + +#include <thread> + +#include "ScopedSignalHandler.h" + +static void TestSignalFd(int fd, int signal) { + ASSERT_NE(-1, fd) << strerror(errno); + + ASSERT_EQ(0, raise(signal)); + + signalfd_siginfo sfd_si; + ASSERT_EQ(static_cast<ssize_t>(sizeof(sfd_si)), read(fd, &sfd_si, sizeof(sfd_si))); + + ASSERT_EQ(signal, static_cast<int>(sfd_si.ssi_signo)); + + close(fd); +} + +TEST(sys_signalfd, signalfd) { + SignalMaskRestorer smr; + + sigset_t mask = {}; + sigaddset(&mask, SIGALRM); + ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &mask, nullptr)); + + TestSignalFd(signalfd(-1, &mask, SFD_CLOEXEC), SIGALRM); +} + +TEST(sys_signalfd, signalfd64) { +#if defined(__BIONIC__) + SignalMaskRestorer smr; -#include "private/ErrnoRestorer.h" + sigset64_t mask = {}; + sigaddset64(&mask, SIGRTMIN); + ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &mask, nullptr)); -int pthread_sigmask(int how, const sigset_t* new_set, sigset_t* old_set) { - ErrnoRestorer errno_restorer; - int result = sigprocmask(how, new_set, old_set); - return (result == -1) ? errno : 0; + TestSignalFd(signalfd64(-1, &mask, SFD_CLOEXEC), SIGRTMIN); +#endif } |