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 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 73bdd1243dSDimitry Andric MainLoopPosix::RunImpl::RunImpl(MainLoopPosix &loop) : loop(loop) { 74bdd1243dSDimitry Andric in_events.reserve(loop.m_read_fds.size()); 75bdd1243dSDimitry Andric } 76bdd1243dSDimitry Andric 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 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 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 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); 125bdd1243dSDimitry Andric (void)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__ 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, 159*cbe9438cSDimitry Andric &extra_data) == -1) { 160*cbe9438cSDimitry Andric if (errno != EINTR) 161bdd1243dSDimitry Andric return Status(errno, eErrorTypePOSIX); 162*cbe9438cSDimitry Andric else 163*cbe9438cSDimitry Andric FD_ZERO(&read_fd_set); 164*cbe9438cSDimitry Andric } 165bdd1243dSDimitry Andric 166bdd1243dSDimitry Andric return Status(); 167bdd1243dSDimitry Andric } 168bdd1243dSDimitry Andric #else 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 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); 302bdd1243dSDimitry Andric (void)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); 349bdd1243dSDimitry Andric (void)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