LLDB  mainline
MainLoopPosix.cpp
Go to the documentation of this file.
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 
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 
35 using namespace lldb;
36 using namespace lldb_private;
37 
38 static sig_atomic_t g_signal_flags[NSIG];
39 
40 static void SignalHandler(int signo, siginfo_t *info, void *) {
41  assert(signo < NSIG);
42  g_signal_flags[signo] = 1;
43 }
44 
46 public:
47  RunImpl(MainLoopPosix &loop);
48  ~RunImpl() = default;
49 
50  Status Poll();
51  void ProcessEvents();
52 
53 private:
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
74  in_events.reserve(loop.m_read_fds.size());
75 }
76 
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 
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
116 #ifndef __ANDROID__
117  read_fds.reserve(loop.m_read_fds.size());
118 #endif
119 }
120 
122  sigset_t sigmask;
123  int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask);
124  assert(ret == 0);
125  (void)ret;
126 
127  for (const auto &sig : loop.m_signals)
128  sigdelset(&sigmask, sig.first);
129  return sigmask;
130 }
131 
132 #ifdef __ANDROID__
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  errno != EINTR)
161  return Status(errno, eErrorTypePOSIX);
162 
163  return Status();
164 }
165 #else
167  read_fds.clear();
168 
169  sigset_t sigmask = get_sigmask();
170 
171  for (const auto &fd : loop.m_read_fds) {
172  struct pollfd pfd;
173  pfd.fd = fd.first;
174  pfd.events = POLLIN;
175  pfd.revents = 0;
176  read_fds.push_back(pfd);
177  }
178 
179  if (ppoll(read_fds.data(), read_fds.size(), nullptr, &sigmask) == -1 &&
180  errno != EINTR)
181  return Status(errno, eErrorTypePOSIX);
182 
183  return Status();
184 }
185 #endif
186 
188 #ifdef __ANDROID__
189  // Collect first all readable file descriptors into a separate vector and
190  // then iterate over it to invoke callbacks. Iterating directly over
191  // loop.m_read_fds is not possible because the callbacks can modify the
192  // container which could invalidate the iterator.
193  std::vector<IOObject::WaitableHandle> fds;
194  for (const auto &fd : loop.m_read_fds)
195  if (FD_ISSET(fd.first, &read_fd_set))
196  fds.push_back(fd.first);
197 
198  for (const auto &handle : fds) {
199 #else
200  for (const auto &fd : read_fds) {
201  if ((fd.revents & (POLLIN | POLLHUP)) == 0)
202  continue;
203  IOObject::WaitableHandle handle = fd.fd;
204 #endif
205  if (loop.m_terminate_request)
206  return;
207 
208  loop.ProcessReadObject(handle);
209  }
210 
211  std::vector<int> signals;
212  for (const auto &entry : loop.m_signals)
213  if (g_signal_flags[entry.first] != 0)
214  signals.push_back(entry.first);
215 
216  for (const auto &signal : signals) {
217  if (loop.m_terminate_request)
218  return;
219  g_signal_flags[signal] = 0;
220  loop.ProcessSignal(signal);
221  }
222 }
223 #endif
224 
225 MainLoopPosix::MainLoopPosix() : m_triggering(false) {
226  Status error = m_trigger_pipe.CreateNew(/*child_process_inherit=*/false);
227  assert(error.Success());
228  const int trigger_pipe_fd = m_trigger_pipe.GetReadFileDescriptor();
229  m_read_fds.insert({trigger_pipe_fd, [trigger_pipe_fd](MainLoopBase &loop) {
230  char c;
231  ssize_t bytes_read = llvm::sys::RetryAfterSignal(
232  -1, ::read, trigger_pipe_fd, &c, 1);
233  assert(bytes_read == 1);
234  UNUSED_IF_ASSERT_DISABLED(bytes_read);
235  // NB: This implicitly causes another loop iteration
236  // and therefore the execution of pending callbacks.
237  }});
238 #if HAVE_SYS_EVENT_H
239  m_kqueue = kqueue();
240  assert(m_kqueue >= 0);
241 #endif
242 }
243 
245 #if HAVE_SYS_EVENT_H
246  close(m_kqueue);
247 #endif
248  m_read_fds.erase(m_trigger_pipe.GetReadFileDescriptor());
249  m_trigger_pipe.Close();
250  assert(m_read_fds.size() == 0);
251  assert(m_signals.size() == 0);
252 }
253 
255 MainLoopPosix::RegisterReadObject(const IOObjectSP &object_sp,
256  const Callback &callback, Status &error) {
257  if (!object_sp || !object_sp->IsValid()) {
258  error.SetErrorString("IO object is not valid.");
259  return nullptr;
260  }
261 
262  const bool inserted =
263  m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second;
264  if (!inserted) {
265  error.SetErrorStringWithFormat("File descriptor %d already monitored.",
266  object_sp->GetWaitableHandle());
267  return nullptr;
268  }
269 
270  return CreateReadHandle(object_sp);
271 }
272 
273 // We shall block the signal, then install the signal handler. The signal will
274 // be unblocked in the Run() function to check for signal delivery.
276 MainLoopPosix::RegisterSignal(int signo, const Callback &callback,
277  Status &error) {
278  auto signal_it = m_signals.find(signo);
279  if (signal_it != m_signals.end()) {
280  auto callback_it = signal_it->second.callbacks.insert(
281  signal_it->second.callbacks.end(), callback);
282  return SignalHandleUP(new SignalHandle(*this, signo, callback_it));
283  }
284 
285  SignalInfo info;
286  info.callbacks.push_back(callback);
287  struct sigaction new_action;
288  new_action.sa_sigaction = &SignalHandler;
289  new_action.sa_flags = SA_SIGINFO;
290  sigemptyset(&new_action.sa_mask);
291  sigaddset(&new_action.sa_mask, signo);
292  sigset_t old_set;
293 
294  g_signal_flags[signo] = 0;
295 
296  // Even if using kqueue, the signal handler will still be invoked, so it's
297  // important to replace it with our "benign" handler.
298  int ret = sigaction(signo, &new_action, &info.old_action);
299  (void)ret;
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
310  // receive it. If using pselect/ppoll, we need to block it, and later unblock
311  // it as a 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  auto insert_ret = m_signals.insert({signo, info});
317 
318  return SignalHandleUP(new SignalHandle(
319  *this, signo, insert_ret.first->second.callbacks.begin()));
320 }
321 
323  bool erased = m_read_fds.erase(handle);
325  assert(erased);
326 }
327 
329  int signo, std::list<Callback>::iterator callback_it) {
330  auto it = m_signals.find(signo);
331  assert(it != m_signals.end());
332 
333  it->second.callbacks.erase(callback_it);
334  // Do not remove the signal handler unless all callbacks have been erased.
335  if (!it->second.callbacks.empty())
336  return;
337 
338  sigaction(signo, &it->second.old_action, nullptr);
339 
340  sigset_t set;
341  sigemptyset(&set);
342  sigaddset(&set, signo);
343  int ret = pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK,
344  &set, nullptr);
345  assert(ret == 0);
346  (void)ret;
347 
348 #if HAVE_SYS_EVENT_H
349  struct kevent ev;
350  EV_SET(&ev, signo, EVFILT_SIGNAL, EV_DELETE, 0, 0, 0);
351  ret = kevent(m_kqueue, &ev, 1, nullptr, 0, nullptr);
352  assert(ret == 0);
353 #endif
354 
355  m_signals.erase(it);
356 }
357 
359  m_terminate_request = false;
360 
361  Status error;
362  RunImpl impl(*this);
363 
364  // run until termination or until we run out of things to listen to
365  // (m_read_fds will always contain m_trigger_pipe fd, so check for > 1)
366  while (!m_terminate_request &&
367  (m_read_fds.size() > 1 || !m_signals.empty())) {
368  error = impl.Poll();
369  if (error.Fail())
370  return error;
371 
372  impl.ProcessEvents();
373 
374  m_triggering = false;
376  }
377  return Status();
378 }
379 
381  auto it = m_read_fds.find(handle);
382  if (it != m_read_fds.end())
383  it->second(*this); // Do the work
384 }
385 
387  auto it = m_signals.find(signo);
388  if (it != m_signals.end()) {
389  // The callback may actually register/unregister signal handlers,
390  // so we need to create a copy first.
391  llvm::SmallVector<Callback, 4> callbacks_to_run{
392  it->second.callbacks.begin(), it->second.callbacks.end()};
393  for (auto &x : callbacks_to_run)
394  x(*this); // Do the work
395  }
396 }
397 
399  if (m_triggering.exchange(true))
400  return;
401 
402  char c = '.';
403  size_t bytes_written;
404  Status error = m_trigger_pipe.Write(&c, 1, bytes_written);
405  assert(error.Success());
407  assert(bytes_written == 1);
408 }
MainLoopPosix.h
lldb_private::MainLoopPosix::SignalInfo::callbacks
std::list< Callback > callbacks
Definition: MainLoopPosix.h:82
lldb_private::MainLoopPosix::RunImpl::read_fds
std::vector< struct pollfd > read_fds
Definition: MainLoopPosix.cpp:65
UNUSED_IF_ASSERT_DISABLED
#define UNUSED_IF_ASSERT_DISABLED(x)
Definition: lldb-defines.h:126
lldb_private::MainLoopPosix::ProcessReadObject
void ProcessReadObject(IOObject::WaitableHandle handle)
Definition: MainLoopPosix.cpp:380
g_signal_flags
static sig_atomic_t g_signal_flags[NSIG]
Definition: MainLoopPosix.cpp:38
lldb_private::MainLoopPosix::TriggerPendingCallbacks
void TriggerPendingCallbacks() override
Definition: MainLoopPosix.cpp:398
lldb_private::MainLoopPosix::UnregisterReadObject
void UnregisterReadObject(IOObject::WaitableHandle handle) override
Definition: MainLoopPosix.cpp:322
lldb_private::MainLoopPosix::ProcessSignal
void ProcessSignal(int signo)
Definition: MainLoopPosix.cpp:386
lldb_private::MainLoopPosix::SignalInfo::was_blocked
bool was_blocked
Definition: MainLoopPosix.h:84
lldb::eErrorTypePOSIX
@ eErrorTypePOSIX
POSIX error codes.
Definition: lldb-enumerations.h:311
lldb_private::MainLoopPosix::RegisterReadObject
ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp, const Callback &callback, Status &error) override
Definition: MainLoopPosix.cpp:255
lldb_private::MainLoopBase
Definition: MainLoopBase.h:36
lldb_private::MainLoopBase::ReadHandleUP
std::unique_ptr< ReadHandle > ReadHandleUP
Definition: MainLoopBase.h:44
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::MainLoopBase::CreateReadHandle
ReadHandleUP CreateReadHandle(const lldb::IOObjectSP &object_sp)
Definition: MainLoopBase.h:66
lldb_private::MainLoopPosix::SignalInfo
Definition: MainLoopPosix.h:81
lldb_private::MainLoopPosix::m_signals
llvm::DenseMap< int, SignalInfo > m_signals
Definition: MainLoopPosix.h:89
lldb_private::MainLoopPosix::m_trigger_pipe
Pipe m_trigger_pipe
Definition: MainLoopPosix.h:90
lldb_private::MainLoopPosix::m_read_fds
llvm::DenseMap< IOObject::WaitableHandle, Callback > m_read_fds
Definition: MainLoopPosix.h:86
lldb_private::MainLoopPosix::~MainLoopPosix
~MainLoopPosix() override
Definition: MainLoopPosix.cpp:244
lldb_private::MainLoopPosix::SignalHandleUP
std::unique_ptr< SignalHandle > SignalHandleUP
Definition: MainLoopPosix.h:29
SignalHandler
static void SignalHandler(int signo, siginfo_t *info, void *)
Definition: MainLoopPosix.cpp:40
set
set(option_framework FRAMEWORK) endif() if(LLDB_ENABLE_PYTHON) get_target_property(python_bindings_dir swig_wrapper_python BINARY_DIR) set(lldb_python_wrapper $
Definition: API/CMakeLists.txt:5
lldb_private::IOObject::WaitableHandle
int WaitableHandle
Definition: IOObject.h:29
lldb_private::MainLoopPosix::RunImpl::get_sigmask
sigset_t get_sigmask()
Definition: MainLoopPosix.cpp:121
lldb_private::MainLoopPosix::RegisterSignal
SignalHandleUP RegisterSignal(int signo, const Callback &callback, Status &error)
Definition: MainLoopPosix.cpp:276
lldb_private::MainLoopPosix
Definition: MainLoopPosix.h:27
lldb_private::MainLoopPosix::Run
Status Run() override
Definition: MainLoopPosix.cpp:358
lldb_private::Status
Definition: Status.h:44
lldb_private::MainLoopBase::m_terminate_request
bool m_terminate_request
Definition: MainLoopBase.h:80
lldb_private::MainLoopPosix::UnregisterSignal
void UnregisterSignal(int signo, std::list< Callback >::iterator callback_it)
Definition: MainLoopPosix.cpp:328
lldb_private::MainLoopPosix::RunImpl::RunImpl
RunImpl(MainLoopPosix &loop)
Definition: MainLoopPosix.cpp:115
Status.h
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::MainLoopPosix::RunImpl::Poll
Status Poll()
Definition: MainLoopPosix.cpp:166
lldb_private::MainLoopPosix::RunImpl::ProcessEvents
void ProcessEvents()
Definition: MainLoopPosix.cpp:187
lldb_private::MainLoopPosix::m_triggering
std::atomic< bool > m_triggering
Definition: MainLoopPosix.h:91
PosixApi.h
lldb_private::MainLoopBase::Callback
std::function< void(MainLoopBase &)> Callback
Definition: MainLoopBase.h:46
lldb_private::MainLoopPosix::SignalInfo::old_action
struct sigaction old_action
Definition: MainLoopPosix.h:83
lldb_private::MainLoopBase::ProcessPendingCallbacks
void ProcessPendingCallbacks()
Definition: MainLoopBase.cpp:22
lldb_private::MainLoopPosix::RunImpl::loop
MainLoopPosix & loop
Definition: MainLoopPosix.cpp:54
lldb
Definition: SBAddress.h:15
lldb_private::MainLoopPosix::RunImpl
Definition: MainLoopPosix.cpp:45
lldb_private::MainLoopPosix::SignalHandle
Definition: MainLoopPosix.h:63