#include <csignal>
#include <time.h>
#include <vector>
+#include <sys/syscall.h>
// Multiplexing is implemented using kqueue on systems that support it (BSD
// variants including OSX). On linux we use ppoll, while android uses pselect
#include <sys/event.h>
#elif defined(LLVM_ON_WIN32)
#include <winsock2.h>
+#elif defined(__ANDROID__)
+#include <sys/syscall.h>
#else
#include <poll.h>
#endif
int num_events = -1;
#else
-#ifdef FORCE_PSELECT
+#ifdef __ANDROID__
fd_set read_fd_set;
#else
std::vector<struct pollfd> read_fds;
}
#else
MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) {
-#ifndef FORCE_PSELECT
+#ifndef __ANDROID__
read_fds.reserve(loop.m_read_fds.size());
#endif
}
#endif
}
-#ifdef FORCE_PSELECT
+#ifdef __ANDROID__
Status MainLoop::RunImpl::Poll() {
+ // ppoll(2) is not supported on older all android versions. Also, older
+ // versions android (API <= 19) implemented pselect in a non-atomic way, as a
+ // combination of pthread_sigmask and select. This is not sufficient for us,
+ // as we rely on the atomicity to correctly implement signal polling, so we
+ // call the underlying syscall ourselves.
+
FD_ZERO(&read_fd_set);
int nfds = 0;
for (const auto &fd : loop.m_read_fds) {
nfds = std::max(nfds, fd.first + 1);
}
- sigset_t sigmask = get_sigmask();
- if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == -1 &&
+ union {
+ sigset_t set;
+ uint64_t pad;
+ } kernel_sigset;
+ memset(&kernel_sigset, 0, sizeof(kernel_sigset));
+ kernel_sigset.set = get_sigmask();
+
+ struct {
+ void *sigset_ptr;
+ size_t sigset_len;
+ } extra_data = {&kernel_sigset, sizeof(kernel_sigset)};
+ if (syscall(__NR_pselect6, nfds, &read_fd_set, nullptr, nullptr, nullptr,
+ &extra_data) == -1 &&
errno != EINTR)
return Status(errno, eErrorTypePOSIX);
#endif
void MainLoop::RunImpl::ProcessEvents() {
-#ifdef FORCE_PSELECT
+#ifdef __ANDROID__
// Collect first all readable file descriptors into a separate vector and then
// iterate over it to invoke callbacks. Iterating directly over
// loop.m_read_fds is not possible because the callbacks can modify the