1 //===-- MainLoopPosix.cpp -------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Host/posix/MainLoopPosix.h" 10 #include "lldb/Host/Config.h" 11 #include "lldb/Host/PosixApi.h" 12 #include "lldb/Utility/Status.h" 13 #include "llvm/Config/llvm-config.h" 14 #include "llvm/Support/Errno.h" 15 #include <algorithm> 16 #include <cassert> 17 #include <cerrno> 18 #include <chrono> 19 #include <csignal> 20 #include <ctime> 21 #include <fcntl.h> 22 #include <vector> 23 24 // Multiplexing is implemented using kqueue on systems that support it (BSD 25 // variants including OSX). On linux we use ppoll. 26 27 #if HAVE_SYS_EVENT_H 28 #include <sys/event.h> 29 #else 30 #include <poll.h> 31 #endif 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 namespace { 37 struct GlobalSignalInfo { 38 sig_atomic_t pipe_fd = -1; 39 static_assert(sizeof(sig_atomic_t) >= sizeof(int), 40 "Type too small for a file descriptor"); 41 sig_atomic_t flag = 0; 42 }; 43 } // namespace 44 static GlobalSignalInfo g_signal_info[NSIG]; 45 46 static void SignalHandler(int signo, siginfo_t *info, void *) { 47 assert(signo < NSIG); 48 49 // Set the flag before writing to the pipe! 50 g_signal_info[signo].flag = 1; 51 52 int fd = g_signal_info[signo].pipe_fd; 53 if (fd < 0) { 54 // This can happen with the following (unlikely) sequence of events: 55 // 1. Thread 1 gets a signal, starts running the signal handler 56 // 2. Thread 2 unregisters the signal handler, setting pipe_fd to -1 57 // 3. Signal handler on thread 1 reads -1 out of pipe_fd 58 // In this case, we can just ignore the signal because we're no longer 59 // interested in it. 60 return; 61 } 62 63 // Write a(ny) character to the pipe to wake up from the poll syscall. 64 char c = '.'; 65 ssize_t bytes_written = llvm::sys::RetryAfterSignal(-1, ::write, fd, &c, 1); 66 // We can safely ignore EAGAIN (pipe full), as that means poll will definitely 67 // return. 68 assert(bytes_written == 1 || (bytes_written == -1 && errno == EAGAIN)); 69 (void)bytes_written; 70 } 71 72 class ToTimeSpec { 73 public: 74 explicit ToTimeSpec(std::optional<MainLoopPosix::TimePoint> point) { 75 using namespace std::chrono; 76 77 if (!point) { 78 m_ts_ptr = nullptr; 79 return; 80 } 81 nanoseconds dur = std::max(*point - steady_clock::now(), nanoseconds(0)); 82 m_ts_ptr = &m_ts; 83 m_ts.tv_sec = duration_cast<seconds>(dur).count(); 84 m_ts.tv_nsec = (dur % seconds(1)).count(); 85 } 86 ToTimeSpec(const ToTimeSpec &) = delete; 87 ToTimeSpec &operator=(const ToTimeSpec &) = delete; 88 89 operator struct timespec *() { return m_ts_ptr; } 90 91 private: 92 struct timespec m_ts; 93 struct timespec *m_ts_ptr; 94 }; 95 96 class MainLoopPosix::RunImpl { 97 public: 98 RunImpl(MainLoopPosix &loop); 99 ~RunImpl() = default; 100 101 Status Poll(); 102 103 void ProcessReadEvents(); 104 105 private: 106 MainLoopPosix &loop; 107 108 #if HAVE_SYS_EVENT_H 109 std::vector<struct kevent> in_events; 110 struct kevent out_events[4]; 111 int num_events = -1; 112 113 #else 114 std::vector<struct pollfd> read_fds; 115 #endif 116 }; 117 118 #if HAVE_SYS_EVENT_H 119 MainLoopPosix::RunImpl::RunImpl(MainLoopPosix &loop) : loop(loop) { 120 in_events.reserve(loop.m_read_fds.size()); 121 } 122 123 Status MainLoopPosix::RunImpl::Poll() { 124 in_events.resize(loop.m_read_fds.size()); 125 unsigned i = 0; 126 for (auto &fd : loop.m_read_fds) 127 EV_SET(&in_events[i++], fd.first, EVFILT_READ, EV_ADD, 0, 0, 0); 128 129 num_events = 130 kevent(loop.m_kqueue, in_events.data(), in_events.size(), out_events, 131 std::size(out_events), ToTimeSpec(loop.GetNextWakeupTime())); 132 133 if (num_events < 0) { 134 if (errno == EINTR) { 135 // in case of EINTR, let the main loop run one iteration 136 // we need to zero num_events to avoid assertions failing 137 num_events = 0; 138 } else 139 return Status(errno, eErrorTypePOSIX); 140 } 141 return Status(); 142 } 143 144 void MainLoopPosix::RunImpl::ProcessReadEvents() { 145 assert(num_events >= 0); 146 for (int i = 0; i < num_events; ++i) { 147 if (loop.m_terminate_request) 148 return; 149 switch (out_events[i].filter) { 150 case EVFILT_READ: 151 loop.ProcessReadObject(out_events[i].ident); 152 break; 153 default: 154 llvm_unreachable("Unknown event"); 155 } 156 } 157 } 158 #else 159 MainLoopPosix::RunImpl::RunImpl(MainLoopPosix &loop) : loop(loop) { 160 read_fds.reserve(loop.m_read_fds.size()); 161 } 162 163 static int StartPoll(llvm::MutableArrayRef<struct pollfd> fds, 164 std::optional<MainLoopPosix::TimePoint> point) { 165 #if HAVE_PPOLL 166 return ppoll(fds.data(), fds.size(), ToTimeSpec(point), 167 /*sigmask=*/nullptr); 168 #else 169 using namespace std::chrono; 170 int timeout = -1; 171 if (point) { 172 nanoseconds dur = std::max(*point - steady_clock::now(), nanoseconds(0)); 173 timeout = ceil<milliseconds>(dur).count(); 174 } 175 return poll(fds.data(), fds.size(), timeout); 176 #endif 177 } 178 179 Status MainLoopPosix::RunImpl::Poll() { 180 read_fds.clear(); 181 182 for (const auto &fd : loop.m_read_fds) { 183 struct pollfd pfd; 184 pfd.fd = fd.first; 185 pfd.events = POLLIN; 186 pfd.revents = 0; 187 read_fds.push_back(pfd); 188 } 189 int ready = StartPoll(read_fds, loop.GetNextWakeupTime()); 190 191 if (ready == -1 && errno != EINTR) 192 return Status(errno, eErrorTypePOSIX); 193 194 return Status(); 195 } 196 197 void MainLoopPosix::RunImpl::ProcessReadEvents() { 198 for (const auto &fd : read_fds) { 199 if ((fd.revents & (POLLIN | POLLHUP)) == 0) 200 continue; 201 IOObject::WaitableHandle handle = fd.fd; 202 if (loop.m_terminate_request) 203 return; 204 205 loop.ProcessReadObject(handle); 206 } 207 } 208 #endif 209 210 MainLoopPosix::MainLoopPosix() { 211 Status error = m_interrupt_pipe.CreateNew(/*child_process_inherit=*/false); 212 assert(error.Success()); 213 214 // Make the write end of the pipe non-blocking. 215 int result = fcntl(m_interrupt_pipe.GetWriteFileDescriptor(), F_SETFL, 216 fcntl(m_interrupt_pipe.GetWriteFileDescriptor(), F_GETFL) | 217 O_NONBLOCK); 218 assert(result == 0); 219 UNUSED_IF_ASSERT_DISABLED(result); 220 221 const int interrupt_pipe_fd = m_interrupt_pipe.GetReadFileDescriptor(); 222 m_read_fds.insert( 223 {interrupt_pipe_fd, [interrupt_pipe_fd](MainLoopBase &loop) { 224 char c; 225 ssize_t bytes_read = 226 llvm::sys::RetryAfterSignal(-1, ::read, interrupt_pipe_fd, &c, 1); 227 assert(bytes_read == 1); 228 UNUSED_IF_ASSERT_DISABLED(bytes_read); 229 // NB: This implicitly causes another loop iteration 230 // and therefore the execution of pending callbacks. 231 }}); 232 #if HAVE_SYS_EVENT_H 233 m_kqueue = kqueue(); 234 assert(m_kqueue >= 0); 235 #endif 236 } 237 238 MainLoopPosix::~MainLoopPosix() { 239 #if HAVE_SYS_EVENT_H 240 close(m_kqueue); 241 #endif 242 m_read_fds.erase(m_interrupt_pipe.GetReadFileDescriptor()); 243 m_interrupt_pipe.Close(); 244 assert(m_read_fds.size() == 0); 245 assert(m_signals.size() == 0); 246 } 247 248 MainLoopPosix::ReadHandleUP 249 MainLoopPosix::RegisterReadObject(const IOObjectSP &object_sp, 250 const Callback &callback, Status &error) { 251 if (!object_sp || !object_sp->IsValid()) { 252 error = Status::FromErrorString("IO object is not valid."); 253 return nullptr; 254 } 255 256 const bool inserted = 257 m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second; 258 if (!inserted) { 259 error = Status::FromErrorStringWithFormat( 260 "File descriptor %d already monitored.", 261 object_sp->GetWaitableHandle()); 262 return nullptr; 263 } 264 265 return CreateReadHandle(object_sp); 266 } 267 268 // We shall block the signal, then install the signal handler. The signal will 269 // be unblocked in the Run() function to check for signal delivery. 270 MainLoopPosix::SignalHandleUP 271 MainLoopPosix::RegisterSignal(int signo, const Callback &callback, 272 Status &error) { 273 auto signal_it = m_signals.find(signo); 274 if (signal_it != m_signals.end()) { 275 auto callback_it = signal_it->second.callbacks.insert( 276 signal_it->second.callbacks.end(), callback); 277 return SignalHandleUP(new SignalHandle(*this, signo, callback_it)); 278 } 279 280 SignalInfo info; 281 info.callbacks.push_back(callback); 282 struct sigaction new_action; 283 new_action.sa_sigaction = &SignalHandler; 284 new_action.sa_flags = SA_SIGINFO; 285 sigemptyset(&new_action.sa_mask); 286 sigaddset(&new_action.sa_mask, signo); 287 sigset_t old_set; 288 289 // Set signal info before installing the signal handler! 290 g_signal_info[signo].pipe_fd = m_interrupt_pipe.GetWriteFileDescriptor(); 291 g_signal_info[signo].flag = 0; 292 293 int ret = sigaction(signo, &new_action, &info.old_action); 294 UNUSED_IF_ASSERT_DISABLED(ret); 295 assert(ret == 0 && "sigaction failed"); 296 297 ret = pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, &old_set); 298 assert(ret == 0 && "pthread_sigmask failed"); 299 info.was_blocked = sigismember(&old_set, signo); 300 auto insert_ret = m_signals.insert({signo, info}); 301 302 return SignalHandleUP(new SignalHandle( 303 *this, signo, insert_ret.first->second.callbacks.begin())); 304 } 305 306 void MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle) { 307 bool erased = m_read_fds.erase(handle); 308 UNUSED_IF_ASSERT_DISABLED(erased); 309 assert(erased); 310 } 311 312 void MainLoopPosix::UnregisterSignal( 313 int signo, std::list<Callback>::iterator callback_it) { 314 auto it = m_signals.find(signo); 315 assert(it != m_signals.end()); 316 317 it->second.callbacks.erase(callback_it); 318 // Do not remove the signal handler unless all callbacks have been erased. 319 if (!it->second.callbacks.empty()) 320 return; 321 322 sigaction(signo, &it->second.old_action, nullptr); 323 324 sigset_t set; 325 sigemptyset(&set); 326 sigaddset(&set, signo); 327 int ret = pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, 328 &set, nullptr); 329 assert(ret == 0); 330 UNUSED_IF_ASSERT_DISABLED(ret); 331 332 m_signals.erase(it); 333 g_signal_info[signo] = {}; 334 } 335 336 Status MainLoopPosix::Run() { 337 m_terminate_request = false; 338 339 Status error; 340 RunImpl impl(*this); 341 342 while (!m_terminate_request) { 343 error = impl.Poll(); 344 if (error.Fail()) 345 return error; 346 347 impl.ProcessReadEvents(); 348 349 ProcessSignals(); 350 351 m_interrupting = false; 352 ProcessCallbacks(); 353 } 354 return Status(); 355 } 356 357 void MainLoopPosix::ProcessReadObject(IOObject::WaitableHandle handle) { 358 auto it = m_read_fds.find(handle); 359 if (it != m_read_fds.end()) 360 it->second(*this); // Do the work 361 } 362 363 void MainLoopPosix::ProcessSignals() { 364 std::vector<int> signals; 365 for (const auto &entry : m_signals) 366 if (g_signal_info[entry.first].flag != 0) 367 signals.push_back(entry.first); 368 369 for (const auto &signal : signals) { 370 if (m_terminate_request) 371 return; 372 373 g_signal_info[signal].flag = 0; 374 ProcessSignal(signal); 375 } 376 } 377 378 void MainLoopPosix::ProcessSignal(int signo) { 379 auto it = m_signals.find(signo); 380 if (it != m_signals.end()) { 381 // The callback may actually register/unregister signal handlers, 382 // so we need to create a copy first. 383 llvm::SmallVector<Callback, 4> callbacks_to_run{ 384 it->second.callbacks.begin(), it->second.callbacks.end()}; 385 for (auto &x : callbacks_to_run) 386 x(*this); // Do the work 387 } 388 } 389 390 void MainLoopPosix::Interrupt() { 391 if (m_interrupting.exchange(true)) 392 return; 393 394 char c = '.'; 395 size_t bytes_written; 396 Status error = m_interrupt_pipe.Write(&c, 1, bytes_written); 397 assert(error.Success()); 398 UNUSED_IF_ASSERT_DISABLED(error); 399 assert(bytes_written == 1); 400 } 401