Add `sigset64_t` and accompanying functions.
This doesn't address `struct sigaction` and `sigaction`. That will
come later.
Bug: http://b/72493232
Test: ran tests
Change-Id: I4134346757ce3a4dac6feae413361cec16223386
diff --git a/docs/32-bit-abi.md b/docs/32-bit-abi.md
index 9ae1973..21f9b71 100644
--- a/docs/32-bit-abi.md
+++ b/docs/32-bit-abi.md
@@ -64,7 +64,9 @@
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 @@
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 2ea8514..0f58204 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1248,9 +1248,6 @@
"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 @@
"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 @@
"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 5c9a284..5c63c0f 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -229,12 +229,12 @@
# 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 @@
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_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 9f1c31f..ec26a50 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 @@
// 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 @@
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 deb19da..0000000
--- 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 2a0779a..534a804 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 dbc9584..1d72fe5 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 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 @@
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 e3bb112..2edfe97 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 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 @@
// 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/pthread_sigmask.cpp b/libc/bionic/pthread_sigmask.cpp
deleted file mode 100644
index 79f31a1..0000000
--- a/libc/bionic/pthread_sigmask.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2008 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 "private/ErrnoRestorer.h"
-
-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;
-}
diff --git a/libc/bionic/signal.cpp b/libc/bionic/signal.cpp
index 9a23416..099944a 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 @@
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;
-
- sigemptyset(&in.set);
- in.mask = mask;
-
- if (sigprocmask(SIG_BLOCK, &in.set, &out.set) == -1) return -1;
- return out.mask;
+int sigaddset(sigset_t* set, int sig) {
+ return SigAddSet(set, sig);
}
-int sigdelset(sigset_t* set, int signum) {
- int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+int sigaddset64(sigset64_t* set, int sig) {
+ return SigAddSet(set, sig);
+}
+
+// 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;
+}
+
+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 @@
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 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, 0xff, sizeof(*set));
return 0;
}
int sigfillset(sigset_t* set) {
- if (set == NULL) {
- errno = EINVAL;
- return -1;
- }
- memset(set, ~0, sizeof(sigset_t));
- return 0;
+ 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 @@
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 @@
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;
-
- sigemptyset(&in.set);
- in.mask = mask;
-
- if (sigprocmask(SIG_SETMASK, &in.set, &out.set) == -1) return -1;
- return out.mask;
+ SigSetConverter in, out;
+ sigemptyset(&in.sigset);
+ in.bsd = mask;
+ if (sigprocmask(SIG_SETMASK, &in.sigset, &out.sigset) == -1) return -1;
+ return out.bsd;
}
int sigsuspend(const sigset_t* bionic_set) {
- kernel_sigset_t set(bionic_set);
- return __rt_sigsuspend(&set, sizeof(set));
+ SigSetConverter set = {};
+ set.sigset = *bionic_set;
+ return __rt_sigsuspend(&set.sigset64, 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 sigsuspend64(const sigset64_t* set) {
+ return __rt_sigsuspend(set, sizeof(*set));
}
-int sigwait(const sigset_t* set, int* sig) {
- kernel_sigset_t sigset(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 sigtimedwait64(const sigset64_t* set, siginfo_t* info, const timespec* timeout) {
+ return __rt_sigtimedwait(set, info, timeout, sizeof(*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 e5075f5..7422a0b 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 @@
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 @@
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 @@
}
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_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
similarity index 68%
rename from libc/bionic/epoll_pwait.cpp
rename to libc/bionic/sys_epoll.cpp
index f3af93e..9f82912 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 63e1db4..53d1f25 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 8517dc6..9ca1cf8 100644
--- a/libc/include/poll.h
+++ b/libc/include/poll.h
@@ -40,6 +40,7 @@
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 d9c9ee2..61bb395 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -80,6 +80,13 @@
#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 @@
#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 @@
#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 @@
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 b5ac586..2e239bf 100644
--- a/libc/include/spawn.h
+++ b/libc/include/spawn.h
@@ -63,10 +63,14 @@
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 2bc16f5..a213a90 100644
--- a/libc/include/sys/epoll.h
+++ b/libc/include/sys/epoll.h
@@ -58,6 +58,7 @@
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 ac51d3f..603a5a6 100644
--- a/libc/include/sys/select.h
+++ b/libc/include/sys/select.h
@@ -75,6 +75,7 @@
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 315622c..2337cd7 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 1ed4ec6..c345ba6 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1325,6 +1325,7 @@
endhostent;
endnetent;
endprotoent;
+ epoll_pwait64;
fexecve;
fflush_unlocked;
fgetc_unlocked;
@@ -1356,28 +1357,47 @@
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 f511707..3af0d42 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1245,6 +1245,7 @@
endhostent;
endnetent;
endprotoent;
+ epoll_pwait64;
fexecve;
fflush_unlocked;
fgetc_unlocked;
@@ -1276,28 +1277,47 @@
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 0960560..5c54ba1 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1350,6 +1350,7 @@
endhostent;
endnetent;
endprotoent;
+ epoll_pwait64;
fexecve;
fflush_unlocked;
fgetc_unlocked;
@@ -1381,28 +1382,47 @@
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 1160f87..c364608 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1309,6 +1309,7 @@
endhostent;
endnetent;
endprotoent;
+ epoll_pwait64;
fexecve;
fflush_unlocked;
fgetc_unlocked;
@@ -1340,28 +1341,47 @@
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 f511707..3af0d42 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1245,6 +1245,7 @@
endhostent;
endnetent;
endprotoent;
+ epoll_pwait64;
fexecve;
fflush_unlocked;
fgetc_unlocked;
@@ -1276,28 +1277,47 @@
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 b0b4b16..eec2c19 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1307,6 +1307,7 @@
endhostent;
endnetent;
endprotoent;
+ epoll_pwait64;
fexecve;
fflush_unlocked;
fgetc_unlocked;
@@ -1338,28 +1339,47 @@
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 f511707..3af0d42 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1245,6 +1245,7 @@
endhostent;
endnetent;
endprotoent;
+ epoll_pwait64;
fexecve;
fflush_unlocked;
fgetc_unlocked;
@@ -1276,28 +1277,47 @@
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 c3ab307..7582068 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 @@
}
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
similarity index 85%
rename from libc/bionic/epoll_create.cpp
rename to libc/private/SigSetConverter.h
index 74f664f..7d0b215 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 bdfb729..0000000
--- 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 25377df..443fe8e 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -140,6 +140,7 @@
"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 71f22dc..85c41a8 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 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 9ecb10c..f812df5 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -356,9 +356,9 @@
}
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 @@
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];
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index 5cbec88..ebc079e 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 @@
// 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 @@
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 @@
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); });
-static void SigSuspendTestHelper(int) {
- ++g_sigsuspend_test_helper_call_count;
+ 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);
+
+ 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 @@
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, 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 @@
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 @@
// 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,18 +519,20 @@
<< 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
}
-#endif
-#endif
-
TEST(signal, sigignore_EINVAL) {
errno = 0;
ASSERT_EQ(-1, sigignore(99999));
diff --git a/tests/spawn_test.cpp b/tests/spawn_test.cpp
index dfce0dc..84df16d 100644
--- a/tests/spawn_test.cpp
+++ b/tests/spawn_test.cpp
@@ -96,6 +96,25 @@
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 @@
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 d1b411a..7233ccc 100644
--- a/tests/sys_epoll_test.cpp
+++ b/tests/sys_epoll_test.cpp
@@ -35,6 +35,11 @@
// 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/tests/sys_signalfd_test.cpp b/tests/sys_signalfd_test.cpp
new file mode 100644
index 0000000..67a72e0
--- /dev/null
+++ b/tests/sys_signalfd_test.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include <errno.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;
+
+ sigset64_t mask = {};
+ sigaddset64(&mask, SIGRTMIN);
+ ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &mask, nullptr));
+
+ TestSignalFd(signalfd64(-1, &mask, SFD_CLOEXEC), SIGRTMIN);
+#endif
+}