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