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