MainLoop.cpp revision 344779
1//===-- MainLoop.cpp --------------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/Config/llvm-config.h"
11
12#include "lldb/Host/MainLoop.h"
13#include "lldb/Host/PosixApi.h"
14#include "lldb/Utility/Status.h"
15#include <algorithm>
16#include <cassert>
17#include <cerrno>
18#include <csignal>
19#include <time.h>
20#include <vector>
21
22// Multiplexing is implemented using kqueue on systems that support it (BSD
23// variants including OSX). On linux we use ppoll, while android uses pselect
24// (ppoll is present but not implemented properly). On windows we use WSApoll
25// (which does not support signals).
26
27#if HAVE_SYS_EVENT_H
28#include <sys/event.h>
29#elif defined(_WIN32)
30#include <winsock2.h>
31#elif defined(__ANDROID__)
32#include <sys/syscall.h>
33#else
34#include <poll.h>
35#endif
36
37#ifdef _WIN32
38#define POLL WSAPoll
39#else
40#define POLL poll
41#endif
42
43#if SIGNAL_POLLING_UNSUPPORTED
44#ifdef _WIN32
45typedef int sigset_t;
46typedef int siginfo_t;
47#endif
48
49int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout_ts,
50          const sigset_t *) {
51  int timeout =
52      (timeout_ts == nullptr)
53          ? -1
54          : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000);
55  return POLL(fds, nfds, timeout);
56}
57
58#endif
59
60using namespace lldb;
61using namespace lldb_private;
62
63static sig_atomic_t g_signal_flags[NSIG];
64
65static void SignalHandler(int signo, siginfo_t *info, void *) {
66  assert(signo < NSIG);
67  g_signal_flags[signo] = 1;
68}
69
70class MainLoop::RunImpl {
71public:
72  RunImpl(MainLoop &loop);
73  ~RunImpl() = default;
74
75  Status Poll();
76  void ProcessEvents();
77
78private:
79  MainLoop &loop;
80
81#if HAVE_SYS_EVENT_H
82  std::vector<struct kevent> in_events;
83  struct kevent out_events[4];
84  int num_events = -1;
85
86#else
87#ifdef __ANDROID__
88  fd_set read_fd_set;
89#else
90  std::vector<struct pollfd> read_fds;
91#endif
92
93  sigset_t get_sigmask();
94#endif
95};
96
97#if HAVE_SYS_EVENT_H
98MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) {
99  in_events.reserve(loop.m_read_fds.size());
100}
101
102Status MainLoop::RunImpl::Poll() {
103  in_events.resize(loop.m_read_fds.size());
104  unsigned i = 0;
105  for (auto &fd : loop.m_read_fds)
106    EV_SET(&in_events[i++], fd.first, EVFILT_READ, EV_ADD, 0, 0, 0);
107
108  num_events = kevent(loop.m_kqueue, in_events.data(), in_events.size(),
109                      out_events, llvm::array_lengthof(out_events), nullptr);
110
111  if (num_events < 0) {
112    if (errno == EINTR) {
113      // in case of EINTR, let the main loop run one iteration
114      // we need to zero num_events to avoid assertions failing
115      num_events = 0;
116    } else
117      return Status(errno, eErrorTypePOSIX);
118  }
119  return Status();
120}
121
122void MainLoop::RunImpl::ProcessEvents() {
123  assert(num_events >= 0);
124  for (int i = 0; i < num_events; ++i) {
125    if (loop.m_terminate_request)
126      return;
127    switch (out_events[i].filter) {
128    case EVFILT_READ:
129      loop.ProcessReadObject(out_events[i].ident);
130      break;
131    case EVFILT_SIGNAL:
132      loop.ProcessSignal(out_events[i].ident);
133      break;
134    default:
135      llvm_unreachable("Unknown event");
136    }
137  }
138}
139#else
140MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) {
141#ifndef __ANDROID__
142  read_fds.reserve(loop.m_read_fds.size());
143#endif
144}
145
146sigset_t MainLoop::RunImpl::get_sigmask() {
147#if SIGNAL_POLLING_UNSUPPORTED
148  return 0;
149#else
150  sigset_t sigmask;
151  int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask);
152  assert(ret == 0);
153  (void) ret;
154
155  for (const auto &sig : loop.m_signals)
156    sigdelset(&sigmask, sig.first);
157  return sigmask;
158#endif
159}
160
161#ifdef __ANDROID__
162Status MainLoop::RunImpl::Poll() {
163  // ppoll(2) is not supported on older all android versions. Also, older
164  // versions android (API <= 19) implemented pselect in a non-atomic way, as a
165  // combination of pthread_sigmask and select. This is not sufficient for us,
166  // as we rely on the atomicity to correctly implement signal polling, so we
167  // call the underlying syscall ourselves.
168
169  FD_ZERO(&read_fd_set);
170  int nfds = 0;
171  for (const auto &fd : loop.m_read_fds) {
172    FD_SET(fd.first, &read_fd_set);
173    nfds = std::max(nfds, fd.first + 1);
174  }
175
176  union {
177    sigset_t set;
178    uint64_t pad;
179  } kernel_sigset;
180  memset(&kernel_sigset, 0, sizeof(kernel_sigset));
181  kernel_sigset.set = get_sigmask();
182
183  struct {
184    void *sigset_ptr;
185    size_t sigset_len;
186  } extra_data = {&kernel_sigset, sizeof(kernel_sigset)};
187  if (syscall(__NR_pselect6, nfds, &read_fd_set, nullptr, nullptr, nullptr,
188              &extra_data) == -1 &&
189      errno != EINTR)
190    return Status(errno, eErrorTypePOSIX);
191
192  return Status();
193}
194#else
195Status MainLoop::RunImpl::Poll() {
196  read_fds.clear();
197
198  sigset_t sigmask = get_sigmask();
199
200  for (const auto &fd : loop.m_read_fds) {
201    struct pollfd pfd;
202    pfd.fd = fd.first;
203    pfd.events = POLLIN;
204    pfd.revents = 0;
205    read_fds.push_back(pfd);
206  }
207
208  if (ppoll(read_fds.data(), read_fds.size(), nullptr, &sigmask) == -1 &&
209      errno != EINTR)
210    return Status(errno, eErrorTypePOSIX);
211
212  return Status();
213}
214#endif
215
216void MainLoop::RunImpl::ProcessEvents() {
217#ifdef __ANDROID__
218  // Collect first all readable file descriptors into a separate vector and
219  // then iterate over it to invoke callbacks. Iterating directly over
220  // loop.m_read_fds is not possible because the callbacks can modify the
221  // container which could invalidate the iterator.
222  std::vector<IOObject::WaitableHandle> fds;
223  for (const auto &fd : loop.m_read_fds)
224    if (FD_ISSET(fd.first, &read_fd_set))
225      fds.push_back(fd.first);
226
227  for (const auto &handle : fds) {
228#else
229  for (const auto &fd : read_fds) {
230    if ((fd.revents & (POLLIN | POLLHUP)) == 0)
231      continue;
232    IOObject::WaitableHandle handle = fd.fd;
233#endif
234    if (loop.m_terminate_request)
235      return;
236
237    loop.ProcessReadObject(handle);
238  }
239
240  std::vector<int> signals;
241  for (const auto &entry : loop.m_signals)
242    if (g_signal_flags[entry.first] != 0)
243      signals.push_back(entry.first);
244
245  for (const auto &signal : signals) {
246    if (loop.m_terminate_request)
247      return;
248    g_signal_flags[signal] = 0;
249    loop.ProcessSignal(signal);
250  }
251}
252#endif
253
254MainLoop::MainLoop() {
255#if HAVE_SYS_EVENT_H
256  m_kqueue = kqueue();
257  assert(m_kqueue >= 0);
258#endif
259}
260MainLoop::~MainLoop() {
261#if HAVE_SYS_EVENT_H
262  close(m_kqueue);
263#endif
264  assert(m_read_fds.size() == 0);
265  assert(m_signals.size() == 0);
266}
267
268MainLoop::ReadHandleUP MainLoop::RegisterReadObject(const IOObjectSP &object_sp,
269                                                    const Callback &callback,
270                                                    Status &error) {
271#ifdef _WIN32
272  if (object_sp->GetFdType() != IOObject:: eFDTypeSocket) {
273    error.SetErrorString("MainLoop: non-socket types unsupported on Windows");
274    return nullptr;
275  }
276#endif
277  if (!object_sp || !object_sp->IsValid()) {
278    error.SetErrorString("IO object is not valid.");
279    return nullptr;
280  }
281
282  const bool inserted =
283      m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second;
284  if (!inserted) {
285    error.SetErrorStringWithFormat("File descriptor %d already monitored.",
286                                   object_sp->GetWaitableHandle());
287    return nullptr;
288  }
289
290  return CreateReadHandle(object_sp);
291}
292
293// We shall block the signal, then install the signal handler. The signal will
294// be unblocked in the Run() function to check for signal delivery.
295MainLoop::SignalHandleUP
296MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) {
297#ifdef SIGNAL_POLLING_UNSUPPORTED
298  error.SetErrorString("Signal polling is not supported on this platform.");
299  return nullptr;
300#else
301  if (m_signals.find(signo) != m_signals.end()) {
302    error.SetErrorStringWithFormat("Signal %d already monitored.", signo);
303    return nullptr;
304  }
305
306  SignalInfo info;
307  info.callback = callback;
308  struct sigaction new_action;
309  new_action.sa_sigaction = &SignalHandler;
310  new_action.sa_flags = SA_SIGINFO;
311  sigemptyset(&new_action.sa_mask);
312  sigaddset(&new_action.sa_mask, signo);
313  sigset_t old_set;
314
315  g_signal_flags[signo] = 0;
316
317  // Even if using kqueue, the signal handler will still be invoked, so it's
318  // important to replace it with our "benign" handler.
319  int ret = sigaction(signo, &new_action, &info.old_action);
320  assert(ret == 0 && "sigaction failed");
321
322#if HAVE_SYS_EVENT_H
323  struct kevent ev;
324  EV_SET(&ev, signo, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
325  ret = kevent(m_kqueue, &ev, 1, nullptr, 0, nullptr);
326  assert(ret == 0);
327#endif
328
329  // If we're using kqueue, the signal needs to be unblocked in order to
330  // receive it. If using pselect/ppoll, we need to block it, and later unblock
331  // it as a part of the system call.
332  ret = pthread_sigmask(HAVE_SYS_EVENT_H ? SIG_UNBLOCK : SIG_BLOCK,
333                        &new_action.sa_mask, &old_set);
334  assert(ret == 0 && "pthread_sigmask failed");
335  info.was_blocked = sigismember(&old_set, signo);
336  m_signals.insert({signo, info});
337
338  return SignalHandleUP(new SignalHandle(*this, signo));
339#endif
340}
341
342void MainLoop::UnregisterReadObject(IOObject::WaitableHandle handle) {
343  bool erased = m_read_fds.erase(handle);
344  UNUSED_IF_ASSERT_DISABLED(erased);
345  assert(erased);
346}
347
348void MainLoop::UnregisterSignal(int signo) {
349#if SIGNAL_POLLING_UNSUPPORTED
350  Status("Signal polling is not supported on this platform.");
351#else
352  auto it = m_signals.find(signo);
353  assert(it != m_signals.end());
354
355  sigaction(signo, &it->second.old_action, nullptr);
356
357  sigset_t set;
358  sigemptyset(&set);
359  sigaddset(&set, signo);
360  int ret = pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK,
361                            &set, nullptr);
362  assert(ret == 0);
363  (void)ret;
364
365#if HAVE_SYS_EVENT_H
366  struct kevent ev;
367  EV_SET(&ev, signo, EVFILT_SIGNAL, EV_DELETE, 0, 0, 0);
368  ret = kevent(m_kqueue, &ev, 1, nullptr, 0, nullptr);
369  assert(ret == 0);
370#endif
371
372  m_signals.erase(it);
373#endif
374}
375
376Status MainLoop::Run() {
377  m_terminate_request = false;
378
379  Status error;
380  RunImpl impl(*this);
381
382  // run until termination or until we run out of things to listen to
383  while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) {
384
385    error = impl.Poll();
386    if (error.Fail())
387      return error;
388
389    impl.ProcessEvents();
390
391    if (m_terminate_request)
392      return Status();
393  }
394  return Status();
395}
396
397void MainLoop::ProcessSignal(int signo) {
398  auto it = m_signals.find(signo);
399  if (it != m_signals.end())
400    it->second.callback(*this); // Do the work
401}
402
403void MainLoop::ProcessReadObject(IOObject::WaitableHandle handle) {
404  auto it = m_read_fds.find(handle);
405  if (it != m_read_fds.end())
406    it->second(*this); // Do the work
407}
408