180814287SRaphael Isemann //===-- MainLoop.cpp ------------------------------------------------------===//
211827799SChris Bieneman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
611827799SChris Bieneman //
711827799SChris Bieneman //===----------------------------------------------------------------------===//
811827799SChris Bieneman 
99f3dd759SKamil Rytarowski #include "llvm/Config/llvm-config.h"
107ec933e5SVedant Kumar #include "lldb/Host/Config.h"
1111827799SChris Bieneman 
1211827799SChris Bieneman #include "lldb/Host/MainLoop.h"
13f40f8fc4SPavel Labath #include "lldb/Host/PosixApi.h"
1497206d57SZachary Turner #include "lldb/Utility/Status.h"
1511827799SChris Bieneman #include <algorithm>
1611827799SChris Bieneman #include <cassert>
1711827799SChris Bieneman #include <cerrno>
1811827799SChris Bieneman #include <csignal>
1976e47d48SRaphael Isemann #include <ctime>
2097206d57SZachary Turner #include <vector>
2111827799SChris Bieneman 
224f1f6417SPavel Labath // Multiplexing is implemented using kqueue on systems that support it (BSD
234f1f6417SPavel Labath // variants including OSX). On linux we use ppoll, while android uses pselect
244f1f6417SPavel Labath // (ppoll is present but not implemented properly). On windows we use WSApoll
254f1f6417SPavel Labath // (which does not support signals).
264f1f6417SPavel Labath 
2711827799SChris Bieneman #if HAVE_SYS_EVENT_H
2811827799SChris Bieneman #include <sys/event.h>
29b1cb0b79SNico Weber #elif defined(_WIN32)
3011827799SChris Bieneman #include <winsock2.h>
3137033108SPavel Labath #elif defined(__ANDROID__)
3237033108SPavel Labath #include <sys/syscall.h>
3311827799SChris Bieneman #else
3411827799SChris Bieneman #include <poll.h>
3511827799SChris Bieneman #endif
3611827799SChris Bieneman 
37b1cb0b79SNico Weber #ifdef _WIN32
3811827799SChris Bieneman #define POLL WSAPoll
3911827799SChris Bieneman #else
4011827799SChris Bieneman #define POLL poll
4111827799SChris Bieneman #endif
4211827799SChris Bieneman 
4311827799SChris Bieneman #if SIGNAL_POLLING_UNSUPPORTED
44b1cb0b79SNico Weber #ifdef _WIN32
4511827799SChris Bieneman typedef int sigset_t;
4611827799SChris Bieneman typedef int siginfo_t;
4711827799SChris Bieneman #endif
4811827799SChris Bieneman 
ppoll(struct pollfd * fds,size_t nfds,const struct timespec * timeout_ts,const sigset_t *)4911827799SChris Bieneman int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout_ts,
5011827799SChris Bieneman           const sigset_t *) {
5111827799SChris Bieneman   int timeout =
5211827799SChris Bieneman       (timeout_ts == nullptr)
5311827799SChris Bieneman           ? -1
5411827799SChris Bieneman           : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000);
5511827799SChris Bieneman   return POLL(fds, nfds, timeout);
5611827799SChris Bieneman }
5711827799SChris Bieneman 
5811827799SChris Bieneman #endif
5911827799SChris Bieneman 
6011827799SChris Bieneman using namespace lldb;
6111827799SChris Bieneman using namespace lldb_private;
6211827799SChris Bieneman 
6311827799SChris Bieneman static sig_atomic_t g_signal_flags[NSIG];
6411827799SChris Bieneman 
65b0717666SAlexandre Ganea #ifndef SIGNAL_POLLING_UNSUPPORTED
SignalHandler(int signo,siginfo_t * info,void *)6611827799SChris Bieneman static void SignalHandler(int signo, siginfo_t *info, void *) {
6711827799SChris Bieneman   assert(signo < NSIG);
6811827799SChris Bieneman   g_signal_flags[signo] = 1;
6911827799SChris Bieneman }
70b0717666SAlexandre Ganea #endif
7111827799SChris Bieneman 
72836ad03fSPavel Labath class MainLoop::RunImpl {
73836ad03fSPavel Labath public:
744f1f6417SPavel Labath   RunImpl(MainLoop &loop);
754f1f6417SPavel Labath   ~RunImpl() = default;
76836ad03fSPavel Labath 
7797206d57SZachary Turner   Status Poll();
784f1f6417SPavel Labath   void ProcessEvents();
79836ad03fSPavel Labath 
80836ad03fSPavel Labath private:
81836ad03fSPavel Labath   MainLoop &loop;
82836ad03fSPavel Labath 
83836ad03fSPavel Labath #if HAVE_SYS_EVENT_H
84836ad03fSPavel Labath   std::vector<struct kevent> in_events;
85836ad03fSPavel Labath   struct kevent out_events[4];
86836ad03fSPavel Labath   int num_events = -1;
87836ad03fSPavel Labath 
88836ad03fSPavel Labath #else
8937033108SPavel Labath #ifdef __ANDROID__
90836ad03fSPavel Labath   fd_set read_fd_set;
91836ad03fSPavel Labath #else
92836ad03fSPavel Labath   std::vector<struct pollfd> read_fds;
93836ad03fSPavel Labath #endif
94836ad03fSPavel Labath 
95836ad03fSPavel Labath   sigset_t get_sigmask();
96836ad03fSPavel Labath #endif
97836ad03fSPavel Labath };
98836ad03fSPavel Labath 
99836ad03fSPavel Labath #if HAVE_SYS_EVENT_H
RunImpl(MainLoop & loop)1004f1f6417SPavel Labath MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) {
1014f1f6417SPavel Labath   in_events.reserve(loop.m_read_fds.size());
102836ad03fSPavel Labath }
103836ad03fSPavel Labath 
Poll()10497206d57SZachary Turner Status MainLoop::RunImpl::Poll() {
1054f1f6417SPavel Labath   in_events.resize(loop.m_read_fds.size());
106836ad03fSPavel Labath   unsigned i = 0;
107836ad03fSPavel Labath   for (auto &fd : loop.m_read_fds)
108836ad03fSPavel Labath     EV_SET(&in_events[i++], fd.first, EVFILT_READ, EV_ADD, 0, 0, 0);
109836ad03fSPavel Labath 
1104f1f6417SPavel Labath   num_events = kevent(loop.m_kqueue, in_events.data(), in_events.size(),
111f15014ffSBenjamin Kramer                       out_events, llvm::array_lengthof(out_events), nullptr);
112836ad03fSPavel Labath 
11353eabaabSMichal Gorny   if (num_events < 0) {
11453eabaabSMichal Gorny     if (errno == EINTR) {
11553eabaabSMichal Gorny       // in case of EINTR, let the main loop run one iteration
11653eabaabSMichal Gorny       // we need to zero num_events to avoid assertions failing
11753eabaabSMichal Gorny       num_events = 0;
11853eabaabSMichal Gorny     } else
119c23f82c0SMichal Gorny       return Status(errno, eErrorTypePOSIX);
12053eabaabSMichal Gorny   }
12197206d57SZachary Turner   return Status();
122836ad03fSPavel Labath }
123836ad03fSPavel Labath 
ProcessEvents()1244f1f6417SPavel Labath void MainLoop::RunImpl::ProcessEvents() {
125836ad03fSPavel Labath   assert(num_events >= 0);
126836ad03fSPavel Labath   for (int i = 0; i < num_events; ++i) {
127836ad03fSPavel Labath     if (loop.m_terminate_request)
128836ad03fSPavel Labath       return;
1294f1f6417SPavel Labath     switch (out_events[i].filter) {
1304f1f6417SPavel Labath     case EVFILT_READ:
1314f1f6417SPavel Labath       loop.ProcessReadObject(out_events[i].ident);
1324f1f6417SPavel Labath       break;
1334f1f6417SPavel Labath     case EVFILT_SIGNAL:
1344f1f6417SPavel Labath       loop.ProcessSignal(out_events[i].ident);
1354f1f6417SPavel Labath       break;
1364f1f6417SPavel Labath     default:
1374f1f6417SPavel Labath       llvm_unreachable("Unknown event");
138836ad03fSPavel Labath     }
139836ad03fSPavel Labath   }
1404f1f6417SPavel Labath }
141836ad03fSPavel Labath #else
RunImpl(MainLoop & loop)1424f1f6417SPavel Labath MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) {
14337033108SPavel Labath #ifndef __ANDROID__
1444f1f6417SPavel Labath   read_fds.reserve(loop.m_read_fds.size());
1454f1f6417SPavel Labath #endif
146836ad03fSPavel Labath }
147836ad03fSPavel Labath 
get_sigmask()148836ad03fSPavel Labath sigset_t MainLoop::RunImpl::get_sigmask() {
149836ad03fSPavel Labath   sigset_t sigmask;
150f048d448SMichal Gorny #if defined(_WIN32)
151f048d448SMichal Gorny   sigmask = 0;
152f048d448SMichal Gorny #elif SIGNAL_POLLING_UNSUPPORTED
153f048d448SMichal Gorny   sigemptyset(&sigmask);
154f048d448SMichal Gorny #else
155836ad03fSPavel Labath   int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask);
156836ad03fSPavel Labath   assert(ret == 0);
157836ad03fSPavel Labath   (void) ret;
158836ad03fSPavel Labath 
1594f1f6417SPavel Labath   for (const auto &sig : loop.m_signals)
160836ad03fSPavel Labath     sigdelset(&sigmask, sig.first);
161836ad03fSPavel Labath #endif
162f048d448SMichal Gorny   return sigmask;
163836ad03fSPavel Labath }
164836ad03fSPavel Labath 
16537033108SPavel Labath #ifdef __ANDROID__
Poll()16697206d57SZachary Turner Status MainLoop::RunImpl::Poll() {
16737033108SPavel Labath   // ppoll(2) is not supported on older all android versions. Also, older
16837033108SPavel Labath   // versions android (API <= 19) implemented pselect in a non-atomic way, as a
16937033108SPavel Labath   // combination of pthread_sigmask and select. This is not sufficient for us,
17037033108SPavel Labath   // as we rely on the atomicity to correctly implement signal polling, so we
17137033108SPavel Labath   // call the underlying syscall ourselves.
17237033108SPavel Labath 
173836ad03fSPavel Labath   FD_ZERO(&read_fd_set);
174836ad03fSPavel Labath   int nfds = 0;
175836ad03fSPavel Labath   for (const auto &fd : loop.m_read_fds) {
176836ad03fSPavel Labath     FD_SET(fd.first, &read_fd_set);
177836ad03fSPavel Labath     nfds = std::max(nfds, fd.first + 1);
178836ad03fSPavel Labath   }
179836ad03fSPavel Labath 
18037033108SPavel Labath   union {
18137033108SPavel Labath     sigset_t set;
18237033108SPavel Labath     uint64_t pad;
18337033108SPavel Labath   } kernel_sigset;
18437033108SPavel Labath   memset(&kernel_sigset, 0, sizeof(kernel_sigset));
18537033108SPavel Labath   kernel_sigset.set = get_sigmask();
18637033108SPavel Labath 
18737033108SPavel Labath   struct {
18837033108SPavel Labath     void *sigset_ptr;
18937033108SPavel Labath     size_t sigset_len;
19037033108SPavel Labath   } extra_data = {&kernel_sigset, sizeof(kernel_sigset)};
19137033108SPavel Labath   if (syscall(__NR_pselect6, nfds, &read_fd_set, nullptr, nullptr, nullptr,
19237033108SPavel Labath               &extra_data) == -1 &&
193836ad03fSPavel Labath       errno != EINTR)
19497206d57SZachary Turner     return Status(errno, eErrorTypePOSIX);
195836ad03fSPavel Labath 
19697206d57SZachary Turner   return Status();
197836ad03fSPavel Labath }
198836ad03fSPavel Labath #else
Poll()19997206d57SZachary Turner Status MainLoop::RunImpl::Poll() {
200836ad03fSPavel Labath   read_fds.clear();
201836ad03fSPavel Labath 
202836ad03fSPavel Labath   sigset_t sigmask = get_sigmask();
203836ad03fSPavel Labath 
204836ad03fSPavel Labath   for (const auto &fd : loop.m_read_fds) {
205836ad03fSPavel Labath     struct pollfd pfd;
206836ad03fSPavel Labath     pfd.fd = fd.first;
207836ad03fSPavel Labath     pfd.events = POLLIN;
208836ad03fSPavel Labath     pfd.revents = 0;
209836ad03fSPavel Labath     read_fds.push_back(pfd);
210836ad03fSPavel Labath   }
211836ad03fSPavel Labath 
212836ad03fSPavel Labath   if (ppoll(read_fds.data(), read_fds.size(), nullptr, &sigmask) == -1 &&
213836ad03fSPavel Labath       errno != EINTR)
21497206d57SZachary Turner     return Status(errno, eErrorTypePOSIX);
215836ad03fSPavel Labath 
21697206d57SZachary Turner   return Status();
217836ad03fSPavel Labath }
2184f1f6417SPavel Labath #endif
219836ad03fSPavel Labath 
ProcessEvents()2204f1f6417SPavel Labath void MainLoop::RunImpl::ProcessEvents() {
22137033108SPavel Labath #ifdef __ANDROID__
22205097246SAdrian Prantl   // Collect first all readable file descriptors into a separate vector and
22305097246SAdrian Prantl   // then iterate over it to invoke callbacks. Iterating directly over
2248c5dafdeSPetr Pavlu   // loop.m_read_fds is not possible because the callbacks can modify the
2258c5dafdeSPetr Pavlu   // container which could invalidate the iterator.
2268c5dafdeSPetr Pavlu   std::vector<IOObject::WaitableHandle> fds;
2278c5dafdeSPetr Pavlu   for (const auto &fd : loop.m_read_fds)
2288c5dafdeSPetr Pavlu     if (FD_ISSET(fd.first, &read_fd_set))
2298c5dafdeSPetr Pavlu       fds.push_back(fd.first);
2308c5dafdeSPetr Pavlu 
2318c5dafdeSPetr Pavlu   for (const auto &handle : fds) {
2324f1f6417SPavel Labath #else
233836ad03fSPavel Labath   for (const auto &fd : read_fds) {
234390b4879SPavel Labath     if ((fd.revents & (POLLIN | POLLHUP)) == 0)
235836ad03fSPavel Labath       continue;
2364f1f6417SPavel Labath     IOObject::WaitableHandle handle = fd.fd;
2374f1f6417SPavel Labath #endif
238836ad03fSPavel Labath     if (loop.m_terminate_request)
239836ad03fSPavel Labath       return;
240836ad03fSPavel Labath 
2414f1f6417SPavel Labath     loop.ProcessReadObject(handle);
2424f1f6417SPavel Labath   }
2434f1f6417SPavel Labath 
2448c5dafdeSPetr Pavlu   std::vector<int> signals;
2458c5dafdeSPetr Pavlu   for (const auto &entry : loop.m_signals)
2468c5dafdeSPetr Pavlu     if (g_signal_flags[entry.first] != 0)
2478c5dafdeSPetr Pavlu       signals.push_back(entry.first);
2488c5dafdeSPetr Pavlu 
2498c5dafdeSPetr Pavlu   for (const auto &signal : signals) {
2504f1f6417SPavel Labath     if (loop.m_terminate_request)
2514f1f6417SPavel Labath       return;
2528c5dafdeSPetr Pavlu     g_signal_flags[signal] = 0;
2538c5dafdeSPetr Pavlu     loop.ProcessSignal(signal);
254836ad03fSPavel Labath   }
255836ad03fSPavel Labath }
256836ad03fSPavel Labath #endif
257836ad03fSPavel Labath 
2584f1f6417SPavel Labath MainLoop::MainLoop() {
2594f1f6417SPavel Labath #if HAVE_SYS_EVENT_H
2604f1f6417SPavel Labath   m_kqueue = kqueue();
2614f1f6417SPavel Labath   assert(m_kqueue >= 0);
2624f1f6417SPavel Labath #endif
2634f1f6417SPavel Labath }
26411827799SChris Bieneman MainLoop::~MainLoop() {
2654f1f6417SPavel Labath #if HAVE_SYS_EVENT_H
2664f1f6417SPavel Labath   close(m_kqueue);
2674f1f6417SPavel Labath #endif
26811827799SChris Bieneman   assert(m_read_fds.size() == 0);
26911827799SChris Bieneman   assert(m_signals.size() == 0);
27011827799SChris Bieneman }
27111827799SChris Bieneman 
27297206d57SZachary Turner MainLoop::ReadHandleUP MainLoop::RegisterReadObject(const IOObjectSP &object_sp,
27397206d57SZachary Turner                                                     const Callback &callback,
27497206d57SZachary Turner                                                     Status &error) {
275b1cb0b79SNico Weber #ifdef _WIN32
27611827799SChris Bieneman   if (object_sp->GetFdType() != IOObject:: eFDTypeSocket) {
27711827799SChris Bieneman     error.SetErrorString("MainLoop: non-socket types unsupported on Windows");
27811827799SChris Bieneman     return nullptr;
27911827799SChris Bieneman   }
28011827799SChris Bieneman #endif
28111827799SChris Bieneman   if (!object_sp || !object_sp->IsValid()) {
28211827799SChris Bieneman     error.SetErrorString("IO object is not valid.");
28311827799SChris Bieneman     return nullptr;
28411827799SChris Bieneman   }
28511827799SChris Bieneman 
28611827799SChris Bieneman   const bool inserted =
28711827799SChris Bieneman       m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second;
28811827799SChris Bieneman   if (!inserted) {
28911827799SChris Bieneman     error.SetErrorStringWithFormat("File descriptor %d already monitored.",
29011827799SChris Bieneman                                    object_sp->GetWaitableHandle());
29111827799SChris Bieneman     return nullptr;
29211827799SChris Bieneman   }
29311827799SChris Bieneman 
29411827799SChris Bieneman   return CreateReadHandle(object_sp);
29511827799SChris Bieneman }
29611827799SChris Bieneman 
29711827799SChris Bieneman // We shall block the signal, then install the signal handler. The signal will
29805097246SAdrian Prantl // be unblocked in the Run() function to check for signal delivery.
29911827799SChris Bieneman MainLoop::SignalHandleUP
30097206d57SZachary Turner MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) {
30111827799SChris Bieneman #ifdef SIGNAL_POLLING_UNSUPPORTED
30211827799SChris Bieneman   error.SetErrorString("Signal polling is not supported on this platform.");
30311827799SChris Bieneman   return nullptr;
30411827799SChris Bieneman #else
30508ce2ba5SMichał Górny   auto signal_it = m_signals.find(signo);
30608ce2ba5SMichał Górny   if (signal_it != m_signals.end()) {
30708ce2ba5SMichał Górny     auto callback_it = signal_it->second.callbacks.insert(
30808ce2ba5SMichał Górny         signal_it->second.callbacks.end(), callback);
30908ce2ba5SMichał Górny     return SignalHandleUP(new SignalHandle(*this, signo, callback_it));
31011827799SChris Bieneman   }
31111827799SChris Bieneman 
31211827799SChris Bieneman   SignalInfo info;
31308ce2ba5SMichał Górny   info.callbacks.push_back(callback);
31411827799SChris Bieneman   struct sigaction new_action;
31511827799SChris Bieneman   new_action.sa_sigaction = &SignalHandler;
31611827799SChris Bieneman   new_action.sa_flags = SA_SIGINFO;
31711827799SChris Bieneman   sigemptyset(&new_action.sa_mask);
31811827799SChris Bieneman   sigaddset(&new_action.sa_mask, signo);
31911827799SChris Bieneman   sigset_t old_set;
32011827799SChris Bieneman 
32111827799SChris Bieneman   g_signal_flags[signo] = 0;
32211827799SChris Bieneman 
3234f1f6417SPavel Labath   // Even if using kqueue, the signal handler will still be invoked, so it's
324173946dcSBruce Mitchener   // important to replace it with our "benign" handler.
3254f1f6417SPavel Labath   int ret = sigaction(signo, &new_action, &info.old_action);
3263131aed5SPavel Labath   (void)ret;
3274f1f6417SPavel Labath   assert(ret == 0 && "sigaction failed");
3284f1f6417SPavel Labath 
3294f1f6417SPavel Labath #if HAVE_SYS_EVENT_H
3304f1f6417SPavel Labath   struct kevent ev;
3314f1f6417SPavel Labath   EV_SET(&ev, signo, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
3324f1f6417SPavel Labath   ret = kevent(m_kqueue, &ev, 1, nullptr, 0, nullptr);
3334f1f6417SPavel Labath   assert(ret == 0);
3344f1f6417SPavel Labath #endif
3354f1f6417SPavel Labath 
33605097246SAdrian Prantl   // If we're using kqueue, the signal needs to be unblocked in order to
337173946dcSBruce Mitchener   // receive it. If using pselect/ppoll, we need to block it, and later unblock
33805097246SAdrian Prantl   // it as a part of the system call.
3394f1f6417SPavel Labath   ret = pthread_sigmask(HAVE_SYS_EVENT_H ? SIG_UNBLOCK : SIG_BLOCK,
3404f1f6417SPavel Labath                         &new_action.sa_mask, &old_set);
3414f1f6417SPavel Labath   assert(ret == 0 && "pthread_sigmask failed");
3424f1f6417SPavel Labath   info.was_blocked = sigismember(&old_set, signo);
34308ce2ba5SMichał Górny   auto insert_ret = m_signals.insert({signo, info});
3444f1f6417SPavel Labath 
34508ce2ba5SMichał Górny   return SignalHandleUP(new SignalHandle(
34608ce2ba5SMichał Górny       *this, signo, insert_ret.first->second.callbacks.begin()));
34711827799SChris Bieneman #endif
34811827799SChris Bieneman }
34911827799SChris Bieneman 
350*5b04eb23SMichał Górny void MainLoop::AddPendingCallback(const Callback &callback) {
351*5b04eb23SMichał Górny   m_pending_callbacks.push_back(callback);
352*5b04eb23SMichał Górny }
353*5b04eb23SMichał Górny 
35411827799SChris Bieneman void MainLoop::UnregisterReadObject(IOObject::WaitableHandle handle) {
35511827799SChris Bieneman   bool erased = m_read_fds.erase(handle);
35611827799SChris Bieneman   UNUSED_IF_ASSERT_DISABLED(erased);
35711827799SChris Bieneman   assert(erased);
35811827799SChris Bieneman }
35911827799SChris Bieneman 
36008ce2ba5SMichał Górny void MainLoop::UnregisterSignal(int signo,
36108ce2ba5SMichał Górny                                 std::list<Callback>::iterator callback_it) {
36211827799SChris Bieneman #if SIGNAL_POLLING_UNSUPPORTED
36397206d57SZachary Turner   Status("Signal polling is not supported on this platform.");
36411827799SChris Bieneman #else
36511827799SChris Bieneman   auto it = m_signals.find(signo);
36611827799SChris Bieneman   assert(it != m_signals.end());
36711827799SChris Bieneman 
36808ce2ba5SMichał Górny   it->second.callbacks.erase(callback_it);
36908ce2ba5SMichał Górny   // Do not remove the signal handler unless all callbacks have been erased.
37008ce2ba5SMichał Górny   if (!it->second.callbacks.empty())
37108ce2ba5SMichał Górny     return;
37208ce2ba5SMichał Górny 
37311827799SChris Bieneman   sigaction(signo, &it->second.old_action, nullptr);
37411827799SChris Bieneman 
37511827799SChris Bieneman   sigset_t set;
37611827799SChris Bieneman   sigemptyset(&set);
37711827799SChris Bieneman   sigaddset(&set, signo);
3784f1f6417SPavel Labath   int ret = pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK,
3794f1f6417SPavel Labath                             &set, nullptr);
3804f1f6417SPavel Labath   assert(ret == 0);
3814f1f6417SPavel Labath   (void)ret;
3824f1f6417SPavel Labath 
3834f1f6417SPavel Labath #if HAVE_SYS_EVENT_H
3844f1f6417SPavel Labath   struct kevent ev;
3854f1f6417SPavel Labath   EV_SET(&ev, signo, EVFILT_SIGNAL, EV_DELETE, 0, 0, 0);
3864f1f6417SPavel Labath   ret = kevent(m_kqueue, &ev, 1, nullptr, 0, nullptr);
3874f1f6417SPavel Labath   assert(ret == 0);
3884f1f6417SPavel Labath #endif
38911827799SChris Bieneman 
39011827799SChris Bieneman   m_signals.erase(it);
39111827799SChris Bieneman #endif
39211827799SChris Bieneman }
39311827799SChris Bieneman 
39497206d57SZachary Turner Status MainLoop::Run() {
39511827799SChris Bieneman   m_terminate_request = false;
39611827799SChris Bieneman 
39797206d57SZachary Turner   Status error;
3984f1f6417SPavel Labath   RunImpl impl(*this);
39911827799SChris Bieneman 
40011827799SChris Bieneman   // run until termination or until we run out of things to listen to
40111827799SChris Bieneman   while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) {
40211827799SChris Bieneman 
4034f1f6417SPavel Labath     error = impl.Poll();
404836ad03fSPavel Labath     if (error.Fail())
405836ad03fSPavel Labath       return error;
40611827799SChris Bieneman 
4074f1f6417SPavel Labath     impl.ProcessEvents();
408*5b04eb23SMichał Górny 
409*5b04eb23SMichał Górny     for (const Callback &callback : m_pending_callbacks)
410*5b04eb23SMichał Górny       callback(*this);
411*5b04eb23SMichał Górny     m_pending_callbacks.clear();
41211827799SChris Bieneman   }
41397206d57SZachary Turner   return Status();
41411827799SChris Bieneman }
4154f1f6417SPavel Labath 
4164f1f6417SPavel Labath void MainLoop::ProcessSignal(int signo) {
4174f1f6417SPavel Labath   auto it = m_signals.find(signo);
41808ce2ba5SMichał Górny   if (it != m_signals.end()) {
41908ce2ba5SMichał Górny     // The callback may actually register/unregister signal handlers,
42008ce2ba5SMichał Górny     // so we need to create a copy first.
42108ce2ba5SMichał Górny     llvm::SmallVector<Callback, 4> callbacks_to_run{
42208ce2ba5SMichał Górny         it->second.callbacks.begin(), it->second.callbacks.end()};
42308ce2ba5SMichał Górny     for (auto &x : callbacks_to_run)
42408ce2ba5SMichał Górny       x(*this); // Do the work
42508ce2ba5SMichał Górny   }
4264f1f6417SPavel Labath }
4274f1f6417SPavel Labath 
4284f1f6417SPavel Labath void MainLoop::ProcessReadObject(IOObject::WaitableHandle handle) {
4294f1f6417SPavel Labath   auto it = m_read_fds.find(handle);
4304f1f6417SPavel Labath   if (it != m_read_fds.end())
4314f1f6417SPavel Labath     it->second(*this); // Do the work
4324f1f6417SPavel Labath }
433