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