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