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