diff options
Diffstat (limited to 'source/Host/common/MainLoop.cpp')
-rw-r--r-- | source/Host/common/MainLoop.cpp | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/source/Host/common/MainLoop.cpp b/source/Host/common/MainLoop.cpp index d0e0d00a3151..6cbb5a842562 100644 --- a/source/Host/common/MainLoop.cpp +++ b/source/Host/common/MainLoop.cpp @@ -28,6 +28,8 @@ #include <sys/event.h> #elif defined(LLVM_ON_WIN32) #include <winsock2.h> +#elif defined(__ANDROID__) +#include <sys/syscall.h> #else #include <poll.h> #endif @@ -38,10 +40,6 @@ #define POLL poll #endif -#ifdef __ANDROID__ -#define FORCE_PSELECT -#endif - #if SIGNAL_POLLING_UNSUPPORTED #ifdef LLVM_ON_WIN32 typedef int sigset_t; @@ -86,7 +84,7 @@ private: int num_events = -1; #else -#ifdef FORCE_PSELECT +#ifdef __ANDROID__ fd_set read_fd_set; #else std::vector<struct pollfd> read_fds; @@ -134,7 +132,7 @@ void MainLoop::RunImpl::ProcessEvents() { } #else MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) { -#ifndef FORCE_PSELECT +#ifndef __ANDROID__ read_fds.reserve(loop.m_read_fds.size()); #endif } @@ -154,8 +152,14 @@ sigset_t MainLoop::RunImpl::get_sigmask() { #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) { @@ -163,8 +167,19 @@ Status MainLoop::RunImpl::Poll() { 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); @@ -193,7 +208,7 @@ Status MainLoop::RunImpl::Poll() { #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 @@ -206,7 +221,7 @@ void MainLoop::RunImpl::ProcessEvents() { for (const auto &handle : fds) { #else for (const auto &fd : read_fds) { - if ((fd.revents & POLLIN) == 0) + if ((fd.revents & (POLLIN | POLLHUP)) == 0) continue; IOObject::WaitableHandle handle = fd.fd; #endif |