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