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 | |
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 |
73 | MainLoopPosix::RunImpl::RunImpl(MainLoopPosix &loop) : loop(loop) { |
74 | in_events.reserve(loop.m_read_fds.size()); |
75 | } |
76 | |
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 | |
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 |
115 | MainLoopPosix::RunImpl::RunImpl(MainLoopPosix &loop) : loop(loop) { |
116 | #ifndef __ANDROID__ |
117 | read_fds.reserve(n: loop.m_read_fds.size()); |
118 | #endif |
119 | } |
120 | |
121 | sigset_t MainLoopPosix::RunImpl::get_sigmask() { |
122 | sigset_t sigmask; |
123 | int ret = pthread_sigmask(SIG_SETMASK, newmask: nullptr, oldmask: &sigmask); |
124 | assert(ret == 0); |
125 | UNUSED_IF_ASSERT_DISABLED(ret); |
126 | |
127 | for (const auto &sig : loop.m_signals) |
128 | sigdelset(set: &sigmask, signo: sig.first); |
129 | return sigmask; |
130 | } |
131 | |
132 | #ifdef __ANDROID__ |
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 |
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(x: pfd); |
180 | } |
181 | |
182 | if (ppoll(fds: read_fds.data(), nfds: read_fds.size(), timeout: nullptr, ss: &sigmask) == -1 && |
183 | errno != EINTR) |
184 | return Status(errno, eErrorTypePOSIX); |
185 | |
186 | return Status(); |
187 | } |
188 | #endif |
189 | |
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(x: 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(signo: 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(KV: {trigger_pipe_fd, [trigger_pipe_fd](MainLoopBase &loop) { |
233 | char c; |
234 | ssize_t bytes_read = llvm::sys::RetryAfterSignal( |
235 | Fail: -1, F&: ::read, As: trigger_pipe_fd, As: &c, As: 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(Val: 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(KV: {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(Val: signo); |
282 | if (signal_it != m_signals.end()) { |
283 | auto callback_it = signal_it->second.callbacks.insert( |
284 | position: signal_it->second.callbacks.end(), x: callback); |
285 | return SignalHandleUP(new SignalHandle(*this, signo, callback_it)); |
286 | } |
287 | |
288 | SignalInfo info; |
289 | info.callbacks.push_back(x: callback); |
290 | struct sigaction new_action; |
291 | new_action.sa_sigaction = &SignalHandler; |
292 | new_action.sa_flags = SA_SIGINFO; |
293 | sigemptyset(set: &new_action.sa_mask); |
294 | sigaddset(set: &new_action.sa_mask, signo: 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(sig: signo, act: &new_action, oact: &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 | newmask: &new_action.sa_mask, oldmask: &old_set); |
317 | assert(ret == 0 && "pthread_sigmask failed" ); |
318 | info.was_blocked = sigismember(set: &old_set, signo: signo); |
319 | auto insert_ret = m_signals.insert(KV: {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(Val: 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(Val: signo); |
334 | assert(it != m_signals.end()); |
335 | |
336 | it->second.callbacks.erase(position: 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(sig: signo, act: &it->second.old_action, oact: nullptr); |
342 | |
343 | sigset_t set; |
344 | sigemptyset(set: &set); |
345 | sigaddset(set: &set, signo: signo); |
346 | int ret = pthread_sigmask(how: it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, |
347 | newmask: &set, oldmask: 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(I: 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(Val: 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(Val: 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(i: true)) |
403 | return; |
404 | |
405 | char c = '.'; |
406 | size_t bytes_written; |
407 | Status error = m_trigger_pipe.Write(buf: &c, size: 1, bytes_written); |
408 | assert(error.Success()); |
409 | UNUSED_IF_ASSERT_DISABLED(error); |
410 | assert(bytes_written == 1); |
411 | } |
412 | |