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