summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Labath <labath@google.com>2017-10-30 16:00:13 +0000
committerPavel Labath <labath@google.com>2017-10-30 16:00:13 +0000
commit370331083496f9b8017eab44d1c67c9dd39fdfdd (patch)
tree00c26b0a6d8d9531056291abb536d9c93df4235a
parent05da5b0205aeada52a6838353d214db3723c79c7 (diff)
downloadbcm5719-llvm-370331083496f9b8017eab44d1c67c9dd39fdfdd.tar.gz
bcm5719-llvm-370331083496f9b8017eab44d1c67c9dd39fdfdd.zip
MainLoop: work around an android libc bug
Versions of android before kitkat implemented pselect non-atomically, which caused flakyness, as we were relying on it atomically setting the signal mask to implement waiting for signals. This patch implements a direct call to the the pselect kernel syscall, which does not suffer from this problem. The code itself is not very pretty, but fortunately the uglyness is contained in the android version of the MainLoop::RunImpl::Poll function. llvm-svn: 316915
-rw-r--r--lldb/include/lldb/Host/MainLoop.h6
-rw-r--r--lldb/source/Host/common/MainLoop.cpp32
2 files changed, 27 insertions, 11 deletions
diff --git a/lldb/include/lldb/Host/MainLoop.h b/lldb/include/lldb/Host/MainLoop.h
index eda01c02a20..c59a5aa5b0e 100644
--- a/lldb/include/lldb/Host/MainLoop.h
+++ b/lldb/include/lldb/Host/MainLoop.h
@@ -15,11 +15,7 @@
#include "llvm/ADT/DenseMap.h"
#include <csignal>
-#ifdef __ANDROID__
-#define FORCE_PSELECT
-#endif
-
-#if !HAVE_PPOLL && !HAVE_SYS_EVENT_H && !defined(FORCE_PSELECT)
+#if !HAVE_PPOLL && !HAVE_SYS_EVENT_H && !defined(__ANDROID__)
#define SIGNAL_POLLING_UNSUPPORTED 1
#endif
diff --git a/lldb/source/Host/common/MainLoop.cpp b/lldb/source/Host/common/MainLoop.cpp
index e48882b274e..4f7052a7a22 100644
--- a/lldb/source/Host/common/MainLoop.cpp
+++ b/lldb/source/Host/common/MainLoop.cpp
@@ -18,6 +18,7 @@
#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
@@ -28,6 +29,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
@@ -82,7 +85,7 @@ private:
int num_events = -1;
#else
-#ifdef FORCE_PSELECT
+#ifdef __ANDROID__
fd_set read_fd_set;
#else
std::vector<struct pollfd> read_fds;
@@ -130,7 +133,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
}
@@ -150,8 +153,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) {
@@ -159,8 +168,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);
@@ -189,7 +209,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
OpenPOWER on IntegriCloud