Coverage Report

Created: 2022-01-22 13:19

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