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
35 using namespace lldb;
36 using namespace lldb_private;
37
38 static sig_atomic_t g_signal_flags[NSIG];
39
SignalHandler(int signo,siginfo_t * info,void *)40 static void SignalHandler(int signo, siginfo_t *info, void *) {
41 assert(signo < NSIG);
42 g_signal_flags[signo] = 1;
43 }
44
45 class MainLoopPosix::RunImpl {
46 public:
47 RunImpl(MainLoopPosix &loop);
48 ~RunImpl() = default;
49
50 Status Poll();
51 void ProcessEvents();
52
53 private:
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
RunImpl(MainLoopPosix & loop)73 MainLoopPosix::RunImpl::RunImpl(MainLoopPosix &loop) : loop(loop) {
74 in_events.reserve(loop.m_read_fds.size());
75 }
76
Poll()77 Status 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
ProcessEvents()97 void 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
RunImpl(MainLoopPosix & loop)115 MainLoopPosix::RunImpl::RunImpl(MainLoopPosix &loop) : loop(loop) {
116 #ifndef __ANDROID__
117 read_fds.reserve(loop.m_read_fds.size());
118 #endif
119 }
120
get_sigmask()121 sigset_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__
Poll()133 Status 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
Poll()169 Status 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
ProcessEvents()190 void 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
228 MainLoopPosix::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
247 MainLoopPosix::~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
257 MainLoopPosix::ReadHandleUP
258 MainLoopPosix::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.
278 MainLoopPosix::SignalHandleUP
279 MainLoopPosix::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
325 void MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle) {
326 bool erased = m_read_fds.erase(handle);
327 UNUSED_IF_ASSERT_DISABLED(erased);
328 assert(erased);
329 }
330
331 void 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
361 Status 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
383 void 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
389 void 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
401 void 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