Serenity Operating System
at master 944 lines 32 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2022, kleines Filmröllchen <malu.bertsch@gmail.com> 4 * Copyright (c) 2022, the SerenityOS developers. 5 * 6 * SPDX-License-Identifier: BSD-2-Clause 7 */ 8 9#include <AK/Assertions.h> 10#include <AK/Badge.h> 11#include <AK/Debug.h> 12#include <AK/Format.h> 13#include <AK/IDAllocator.h> 14#include <AK/JsonObject.h> 15#include <AK/JsonValue.h> 16#include <AK/NeverDestroyed.h> 17#include <AK/Singleton.h> 18#include <AK/TemporaryChange.h> 19#include <AK/Time.h> 20#include <LibCore/Event.h> 21#include <LibCore/EventLoop.h> 22#include <LibCore/LocalServer.h> 23#include <LibCore/Notifier.h> 24#include <LibCore/Object.h> 25#include <LibCore/Promise.h> 26#include <LibCore/SessionManagement.h> 27#include <LibCore/Socket.h> 28#include <LibThreading/Mutex.h> 29#include <LibThreading/MutexProtected.h> 30#include <errno.h> 31#include <fcntl.h> 32#include <signal.h> 33#include <stdio.h> 34#include <string.h> 35#include <sys/select.h> 36#include <sys/socket.h> 37#include <sys/time.h> 38#include <sys/types.h> 39#include <time.h> 40#include <unistd.h> 41 42#ifdef AK_OS_SERENITY 43# include <LibCore/Account.h> 44 45extern bool s_global_initializers_ran; 46#endif 47 48namespace Core { 49 50class InspectorServerConnection; 51 52[[maybe_unused]] static bool connect_to_inspector_server(); 53 54struct EventLoopTimer { 55 int timer_id { 0 }; 56 Time interval; 57 Time fire_time; 58 bool should_reload { false }; 59 TimerShouldFireWhenNotVisible fire_when_not_visible { TimerShouldFireWhenNotVisible::No }; 60 WeakPtr<Object> owner; 61 62 void reload(Time const& now); 63 bool has_expired(Time const& now) const; 64}; 65 66struct EventLoop::Private { 67 Threading::Mutex lock; 68}; 69 70static Threading::MutexProtected<NeverDestroyed<IDAllocator>> s_id_allocator; 71static Threading::MutexProtected<RefPtr<InspectorServerConnection>> s_inspector_server_connection; 72 73// Each thread has its own event loop stack, its own timers, notifiers and a wake pipe. 74static thread_local Vector<EventLoop&>* s_event_loop_stack; 75static thread_local HashMap<int, NonnullOwnPtr<EventLoopTimer>>* s_timers; 76static thread_local HashTable<Notifier*>* s_notifiers; 77// The wake pipe is both responsible for notifying us when someone calls wake(), as well as POSIX signals. 78// While wake() pushes zero into the pipe, signal numbers (by defintion nonzero, see signal_numbers.h) are pushed into the pipe verbatim. 79thread_local int EventLoop::s_wake_pipe_fds[2]; 80thread_local bool EventLoop::s_wake_pipe_initialized { false }; 81thread_local bool s_warned_promise_count { false }; 82 83void EventLoop::initialize_wake_pipes() 84{ 85 if (!s_wake_pipe_initialized) { 86#if defined(SOCK_NONBLOCK) 87 int rc = pipe2(s_wake_pipe_fds, O_CLOEXEC); 88#else 89 int rc = pipe(s_wake_pipe_fds); 90 fcntl(s_wake_pipe_fds[0], F_SETFD, FD_CLOEXEC); 91 fcntl(s_wake_pipe_fds[1], F_SETFD, FD_CLOEXEC); 92 93#endif 94 VERIFY(rc == 0); 95 s_wake_pipe_initialized = true; 96 } 97} 98 99bool EventLoop::has_been_instantiated() 100{ 101 return s_event_loop_stack != nullptr && !s_event_loop_stack->is_empty(); 102} 103 104class SignalHandlers : public RefCounted<SignalHandlers> { 105 AK_MAKE_NONCOPYABLE(SignalHandlers); 106 AK_MAKE_NONMOVABLE(SignalHandlers); 107 108public: 109 SignalHandlers(int signo, void (*handle_signal)(int)); 110 ~SignalHandlers(); 111 112 void dispatch(); 113 int add(Function<void(int)>&& handler); 114 bool remove(int handler_id); 115 116 bool is_empty() const 117 { 118 if (m_calling_handlers) { 119 for (auto& handler : m_handlers_pending) { 120 if (handler.value) 121 return false; // an add is pending 122 } 123 } 124 return m_handlers.is_empty(); 125 } 126 127 bool have(int handler_id) const 128 { 129 if (m_calling_handlers) { 130 auto it = m_handlers_pending.find(handler_id); 131 if (it != m_handlers_pending.end()) { 132 if (!it->value) 133 return false; // a deletion is pending 134 } 135 } 136 return m_handlers.contains(handler_id); 137 } 138 139 int m_signo; 140 void (*m_original_handler)(int); // TODO: can't use sighandler_t? 141 HashMap<int, Function<void(int)>> m_handlers; 142 HashMap<int, Function<void(int)>> m_handlers_pending; 143 bool m_calling_handlers { false }; 144}; 145 146struct SignalHandlersInfo { 147 HashMap<int, NonnullRefPtr<SignalHandlers>> signal_handlers; 148 int next_signal_id { 0 }; 149}; 150 151static Singleton<SignalHandlersInfo> s_signals; 152template<bool create_if_null = true> 153inline SignalHandlersInfo* signals_info() 154{ 155 return s_signals.ptr(); 156} 157 158pid_t EventLoop::s_pid; 159 160class InspectorServerConnection : public Object { 161 C_OBJECT(InspectorServerConnection) 162private: 163 explicit InspectorServerConnection(NonnullOwnPtr<LocalSocket> socket) 164 : m_socket(move(socket)) 165 , m_client_id(s_id_allocator.with_locked([](auto& allocator) { 166 return allocator->allocate(); 167 })) 168 { 169#ifdef AK_OS_SERENITY 170 m_socket->on_ready_to_read = [this] { 171 u32 length; 172 auto maybe_bytes_read = m_socket->read_some({ (u8*)&length, sizeof(length) }); 173 if (maybe_bytes_read.is_error()) { 174 dbgln("InspectorServerConnection: Failed to read message length from inspector server connection: {}", maybe_bytes_read.error()); 175 shutdown(); 176 return; 177 } 178 179 auto bytes_read = maybe_bytes_read.release_value(); 180 if (bytes_read.is_empty()) { 181 dbgln_if(EVENTLOOP_DEBUG, "RPC client disconnected"); 182 shutdown(); 183 return; 184 } 185 186 VERIFY(bytes_read.size() == sizeof(length)); 187 188 auto request_buffer = ByteBuffer::create_uninitialized(length).release_value(); 189 maybe_bytes_read = m_socket->read_some(request_buffer.bytes()); 190 if (maybe_bytes_read.is_error()) { 191 dbgln("InspectorServerConnection: Failed to read message content from inspector server connection: {}", maybe_bytes_read.error()); 192 shutdown(); 193 return; 194 } 195 196 bytes_read = maybe_bytes_read.release_value(); 197 198 auto request_json = JsonValue::from_string(request_buffer); 199 if (request_json.is_error() || !request_json.value().is_object()) { 200 dbgln("RPC client sent invalid request"); 201 shutdown(); 202 return; 203 } 204 205 handle_request(request_json.value().as_object()); 206 }; 207#else 208 warnln("RPC Client constructed outside serenity, this is very likely a bug!"); 209#endif 210 } 211 virtual ~InspectorServerConnection() override 212 { 213 if (auto inspected_object = m_inspected_object.strong_ref()) 214 inspected_object->decrement_inspector_count({}); 215 } 216 217public: 218 void send_response(JsonObject const& response) 219 { 220 auto serialized = response.to_deprecated_string(); 221 auto bytes_to_send = serialized.bytes(); 222 u32 length = bytes_to_send.size(); 223 // FIXME: Propagate errors 224 MUST(m_socket->write_value(length)); 225 while (!bytes_to_send.is_empty()) { 226 size_t bytes_sent = MUST(m_socket->write_some(bytes_to_send)); 227 bytes_to_send = bytes_to_send.slice(bytes_sent); 228 } 229 } 230 231 void handle_request(JsonObject const& request) 232 { 233 auto type = request.get_deprecated_string("type"sv); 234 235 if (!type.has_value()) { 236 dbgln("RPC client sent request without type field"); 237 return; 238 } 239 240 if (type == "Identify") { 241 JsonObject response; 242 response.set("type", type.value()); 243 response.set("pid", getpid()); 244#ifdef AK_OS_SERENITY 245 char buffer[1024]; 246 if (get_process_name(buffer, sizeof(buffer)) >= 0) { 247 response.set("process_name", buffer); 248 } else { 249 response.set("process_name", JsonValue()); 250 } 251#endif 252 send_response(response); 253 return; 254 } 255 256 if (type == "GetAllObjects") { 257 JsonObject response; 258 response.set("type", type.value()); 259 JsonArray objects; 260 for (auto& object : Object::all_objects()) { 261 JsonObject json_object; 262 object.save_to(json_object); 263 objects.append(move(json_object)); 264 } 265 response.set("objects", move(objects)); 266 send_response(response); 267 return; 268 } 269 270 if (type == "SetInspectedObject") { 271 auto address = request.get_addr("address"sv); 272 for (auto& object : Object::all_objects()) { 273 if ((FlatPtr)&object == address) { 274 if (auto inspected_object = m_inspected_object.strong_ref()) 275 inspected_object->decrement_inspector_count({}); 276 m_inspected_object = object; 277 object.increment_inspector_count({}); 278 break; 279 } 280 } 281 return; 282 } 283 284 if (type == "SetProperty") { 285 auto address = request.get_addr("address"sv); 286 for (auto& object : Object::all_objects()) { 287 if ((FlatPtr)&object == address) { 288 bool success = object.set_property(request.get_deprecated_string("name"sv).value(), request.get("value"sv).value()); 289 JsonObject response; 290 response.set("type", "SetProperty"); 291 response.set("success", success); 292 send_response(response); 293 break; 294 } 295 } 296 return; 297 } 298 299 if (type == "Disconnect") { 300 shutdown(); 301 return; 302 } 303 } 304 305 void shutdown() 306 { 307 s_id_allocator.with_locked([this](auto& allocator) { allocator->deallocate(m_client_id); }); 308 } 309 310private: 311 NonnullOwnPtr<LocalSocket> m_socket; 312 WeakPtr<Object> m_inspected_object; 313 int m_client_id { -1 }; 314}; 315 316EventLoop::EventLoop([[maybe_unused]] MakeInspectable make_inspectable) 317 : m_wake_pipe_fds(&s_wake_pipe_fds) 318 , m_private(make<Private>()) 319{ 320#ifdef AK_OS_SERENITY 321 if (!s_global_initializers_ran) { 322 // NOTE: Trying to have an event loop as a global variable will lead to initialization-order fiascos, 323 // as the event loop constructor accesses and/or sets other global variables. 324 // Therefore, we crash the program before ASAN catches us. 325 // If you came here because of the assertion failure, please redesign your program to not have global event loops. 326 // The common practice is to initialize the main event loop in the main function, and if necessary, 327 // pass event loop references around or access them with EventLoop::with_main_locked() and EventLoop::current(). 328 VERIFY_NOT_REACHED(); 329 } 330#endif 331 332 if (!s_event_loop_stack) { 333 s_event_loop_stack = new Vector<EventLoop&>; 334 s_timers = new HashMap<int, NonnullOwnPtr<EventLoopTimer>>; 335 s_notifiers = new HashTable<Notifier*>; 336 } 337 338 if (s_event_loop_stack->is_empty()) { 339 s_pid = getpid(); 340 s_event_loop_stack->append(*this); 341 342#ifdef AK_OS_SERENITY 343 if (getuid() != 0) { 344 if (getenv("MAKE_INSPECTABLE") == "1"sv) 345 make_inspectable = Core::EventLoop::MakeInspectable::Yes; 346 347 if (make_inspectable == MakeInspectable::Yes 348 && !s_inspector_server_connection.with_locked([](auto inspector_server_connection) { return inspector_server_connection; })) { 349 if (!connect_to_inspector_server()) 350 dbgln("Core::EventLoop: Failed to connect to InspectorServer"); 351 } 352 } 353#endif 354 } 355 356 initialize_wake_pipes(); 357 358 dbgln_if(EVENTLOOP_DEBUG, "{} Core::EventLoop constructed :)", getpid()); 359} 360 361EventLoop::~EventLoop() 362{ 363 if (!s_event_loop_stack->is_empty() && &s_event_loop_stack->last() == this) 364 s_event_loop_stack->take_last(); 365} 366 367bool connect_to_inspector_server() 368{ 369#ifdef AK_OS_SERENITY 370 auto maybe_path = SessionManagement::parse_path_with_sid("/tmp/session/%sid/portal/inspectables"sv); 371 if (maybe_path.is_error()) { 372 dbgln("connect_to_inspector_server: {}", maybe_path.error()); 373 return false; 374 } 375 auto inspector_server_path = maybe_path.value(); 376 auto maybe_socket = LocalSocket::connect(inspector_server_path, Socket::PreventSIGPIPE::Yes); 377 if (maybe_socket.is_error()) { 378 dbgln("connect_to_inspector_server: Failed to connect: {}", maybe_socket.error()); 379 return false; 380 } 381 s_inspector_server_connection.with_locked([&](auto& inspector_server_connection) { 382 inspector_server_connection = InspectorServerConnection::construct(maybe_socket.release_value()); 383 }); 384 return true; 385#else 386 VERIFY_NOT_REACHED(); 387#endif 388} 389 390#define VERIFY_EVENT_LOOP_INITIALIZED() \ 391 do { \ 392 if (!s_event_loop_stack) { \ 393 warnln("EventLoop static API was called without prior EventLoop init!"); \ 394 VERIFY_NOT_REACHED(); \ 395 } \ 396 } while (0) 397 398EventLoop& EventLoop::current() 399{ 400 VERIFY_EVENT_LOOP_INITIALIZED(); 401 return s_event_loop_stack->last(); 402} 403 404void EventLoop::quit(int code) 405{ 406 dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop::quit({})", code); 407 m_exit_requested = true; 408 m_exit_code = code; 409} 410 411void EventLoop::unquit() 412{ 413 dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop::unquit()"); 414 m_exit_requested = false; 415 m_exit_code = 0; 416} 417 418struct EventLoopPusher { 419public: 420 EventLoopPusher(EventLoop& event_loop) 421 : m_event_loop(event_loop) 422 { 423 if (EventLoop::has_been_instantiated()) { 424 m_event_loop.take_pending_events_from(EventLoop::current()); 425 s_event_loop_stack->append(event_loop); 426 } 427 } 428 ~EventLoopPusher() 429 { 430 if (EventLoop::has_been_instantiated()) { 431 s_event_loop_stack->take_last(); 432 for (auto& job : m_event_loop.m_pending_promises) { 433 // When this event loop was not running below another event loop, the jobs may very well have finished in the meantime. 434 if (!job->is_resolved()) 435 job->cancel(Error::from_string_view("EventLoop is exiting"sv)); 436 } 437 EventLoop::current().take_pending_events_from(m_event_loop); 438 } 439 } 440 441private: 442 EventLoop& m_event_loop; 443}; 444 445int EventLoop::exec() 446{ 447 EventLoopPusher pusher(*this); 448 for (;;) { 449 if (m_exit_requested) 450 return m_exit_code; 451 pump(); 452 } 453 VERIFY_NOT_REACHED(); 454} 455 456void EventLoop::spin_until(Function<bool()> goal_condition) 457{ 458 EventLoopPusher pusher(*this); 459 while (!goal_condition()) 460 pump(); 461} 462 463size_t EventLoop::pump(WaitMode mode) 464{ 465 wait_for_event(mode); 466 467 decltype(m_queued_events) events; 468 { 469 Threading::MutexLocker locker(m_private->lock); 470 events = move(m_queued_events); 471 } 472 473 m_pending_promises.remove_all_matching([](auto& job) { return job->is_resolved() || job->is_canceled(); }); 474 475 size_t processed_events = 0; 476 for (size_t i = 0; i < events.size(); ++i) { 477 auto& queued_event = events.at(i); 478 auto receiver = queued_event.receiver.strong_ref(); 479 auto& event = *queued_event.event; 480 if (receiver) 481 dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop: {} event {}", *receiver, event.type()); 482 483 if (!receiver) { 484 switch (event.type()) { 485 case Event::Quit: 486 VERIFY_NOT_REACHED(); 487 default: 488 dbgln_if(EVENTLOOP_DEBUG, "Event type {} with no receiver :(", event.type()); 489 break; 490 } 491 } else if (event.type() == Event::Type::DeferredInvoke) { 492 dbgln_if(DEFERRED_INVOKE_DEBUG, "DeferredInvoke: receiver = {}", *receiver); 493 static_cast<DeferredInvocationEvent&>(event).m_invokee(); 494 } else { 495 NonnullRefPtr<Object> protector(*receiver); 496 receiver->dispatch_event(event); 497 } 498 ++processed_events; 499 500 if (m_exit_requested) { 501 Threading::MutexLocker locker(m_private->lock); 502 dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop: Exit requested. Rejigging {} events.", events.size() - i); 503 decltype(m_queued_events) new_event_queue; 504 new_event_queue.ensure_capacity(m_queued_events.size() + events.size()); 505 for (++i; i < events.size(); ++i) 506 new_event_queue.unchecked_append(move(events[i])); 507 new_event_queue.extend(move(m_queued_events)); 508 m_queued_events = move(new_event_queue); 509 break; 510 } 511 } 512 513 if (m_pending_promises.size() > 30 && !s_warned_promise_count) { 514 s_warned_promise_count = true; 515 dbgln("EventLoop {:p} warning: Job queue wasn't designed for this load ({} promises). Please begin optimizing EventLoop::pump() -> m_pending_promises.remove_all_matching", this, m_pending_promises.size()); 516 } 517 518 return processed_events; 519} 520 521void EventLoop::post_event(Object& receiver, NonnullOwnPtr<Event>&& event, ShouldWake should_wake) 522{ 523 Threading::MutexLocker lock(m_private->lock); 524 dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop::post_event: ({}) << receiver={}, event={}", m_queued_events.size(), receiver, event); 525 m_queued_events.empend(receiver, move(event)); 526 if (should_wake == ShouldWake::Yes) 527 wake(); 528} 529 530void EventLoop::wake_once(Object& receiver, int custom_event_type) 531{ 532 Threading::MutexLocker lock(m_private->lock); 533 dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop::wake_once: event type {}", custom_event_type); 534 auto identical_events = m_queued_events.find_if([&](auto& queued_event) { 535 if (queued_event.receiver.is_null()) 536 return false; 537 auto const& event = queued_event.event; 538 auto is_receiver_identical = queued_event.receiver.ptr() == &receiver; 539 auto event_id_matches = event->type() == Event::Type::Custom && static_cast<CustomEvent const*>(event.ptr())->custom_type() == custom_event_type; 540 return is_receiver_identical && event_id_matches; 541 }); 542 // Event is not in the queue yet, so we want to wake. 543 if (identical_events.is_end()) 544 post_event(receiver, make<CustomEvent>(custom_event_type), ShouldWake::Yes); 545} 546 547void EventLoop::add_job(NonnullRefPtr<Promise<NonnullRefPtr<Object>>> job_promise) 548{ 549 m_pending_promises.append(move(job_promise)); 550} 551 552SignalHandlers::SignalHandlers(int signo, void (*handle_signal)(int)) 553 : m_signo(signo) 554 , m_original_handler(signal(signo, handle_signal)) 555{ 556 dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop: Registered handler for signal {}", m_signo); 557} 558 559SignalHandlers::~SignalHandlers() 560{ 561 dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop: Unregistering handler for signal {}", m_signo); 562 signal(m_signo, m_original_handler); 563} 564 565void SignalHandlers::dispatch() 566{ 567 TemporaryChange change(m_calling_handlers, true); 568 for (auto& handler : m_handlers) 569 handler.value(m_signo); 570 if (!m_handlers_pending.is_empty()) { 571 // Apply pending adds/removes 572 for (auto& handler : m_handlers_pending) { 573 if (handler.value) { 574 auto result = m_handlers.set(handler.key, move(handler.value)); 575 VERIFY(result == AK::HashSetResult::InsertedNewEntry); 576 } else { 577 m_handlers.remove(handler.key); 578 } 579 } 580 m_handlers_pending.clear(); 581 } 582} 583 584int SignalHandlers::add(Function<void(int)>&& handler) 585{ 586 int id = ++signals_info()->next_signal_id; // TODO: worry about wrapping and duplicates? 587 if (m_calling_handlers) 588 m_handlers_pending.set(id, move(handler)); 589 else 590 m_handlers.set(id, move(handler)); 591 return id; 592} 593 594bool SignalHandlers::remove(int handler_id) 595{ 596 VERIFY(handler_id != 0); 597 if (m_calling_handlers) { 598 auto it = m_handlers.find(handler_id); 599 if (it != m_handlers.end()) { 600 // Mark pending remove 601 m_handlers_pending.set(handler_id, {}); 602 return true; 603 } 604 it = m_handlers_pending.find(handler_id); 605 if (it != m_handlers_pending.end()) { 606 if (!it->value) 607 return false; // already was marked as deleted 608 it->value = nullptr; 609 return true; 610 } 611 return false; 612 } 613 return m_handlers.remove(handler_id); 614} 615 616void EventLoop::dispatch_signal(int signo) 617{ 618 auto& info = *signals_info(); 619 auto handlers = info.signal_handlers.find(signo); 620 if (handlers != info.signal_handlers.end()) { 621 // Make sure we bump the ref count while dispatching the handlers! 622 // This allows a handler to unregister/register while the handlers 623 // are being called! 624 auto handler = handlers->value; 625 dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop: dispatching signal {}", signo); 626 handler->dispatch(); 627 } 628} 629 630void EventLoop::handle_signal(int signo) 631{ 632 VERIFY(signo != 0); 633 // We MUST check if the current pid still matches, because there 634 // is a window between fork() and exec() where a signal delivered 635 // to our fork could be inadvertently routed to the parent process! 636 if (getpid() == s_pid) { 637 int nwritten = write(s_wake_pipe_fds[1], &signo, sizeof(signo)); 638 if (nwritten < 0) { 639 perror("EventLoop::register_signal: write"); 640 VERIFY_NOT_REACHED(); 641 } 642 } else { 643 // We're a fork who received a signal, reset s_pid 644 s_pid = 0; 645 } 646} 647 648int EventLoop::register_signal(int signo, Function<void(int)> handler) 649{ 650 VERIFY(signo != 0); 651 auto& info = *signals_info(); 652 auto handlers = info.signal_handlers.find(signo); 653 if (handlers == info.signal_handlers.end()) { 654 auto signal_handlers = adopt_ref(*new SignalHandlers(signo, EventLoop::handle_signal)); 655 auto handler_id = signal_handlers->add(move(handler)); 656 info.signal_handlers.set(signo, move(signal_handlers)); 657 return handler_id; 658 } else { 659 return handlers->value->add(move(handler)); 660 } 661} 662 663void EventLoop::unregister_signal(int handler_id) 664{ 665 VERIFY(handler_id != 0); 666 int remove_signo = 0; 667 auto& info = *signals_info(); 668 for (auto& h : info.signal_handlers) { 669 auto& handlers = *h.value; 670 if (handlers.remove(handler_id)) { 671 if (handlers.is_empty()) 672 remove_signo = handlers.m_signo; 673 break; 674 } 675 } 676 if (remove_signo != 0) 677 info.signal_handlers.remove(remove_signo); 678} 679 680void EventLoop::notify_forked(ForkEvent event) 681{ 682 VERIFY_EVENT_LOOP_INITIALIZED(); 683 switch (event) { 684 case ForkEvent::Child: 685 s_event_loop_stack->clear(); 686 s_timers->clear(); 687 s_notifiers->clear(); 688 s_wake_pipe_initialized = false; 689 initialize_wake_pipes(); 690 if (auto* info = signals_info<false>()) { 691 info->signal_handlers.clear(); 692 info->next_signal_id = 0; 693 } 694 s_pid = 0; 695 return; 696 } 697 698 VERIFY_NOT_REACHED(); 699} 700 701void EventLoop::wait_for_event(WaitMode mode) 702{ 703 fd_set rfds; 704 fd_set wfds; 705retry: 706 707 // Set up the file descriptors for select(). 708 // Basically, we translate high-level event information into low-level selectable file descriptors. 709 FD_ZERO(&rfds); 710 FD_ZERO(&wfds); 711 712 int max_fd = 0; 713 auto add_fd_to_set = [&max_fd](int fd, fd_set& set) { 714 FD_SET(fd, &set); 715 if (fd > max_fd) 716 max_fd = fd; 717 }; 718 719 int max_fd_added = -1; 720 // The wake pipe informs us of POSIX signals as well as manual calls to wake() 721 add_fd_to_set(s_wake_pipe_fds[0], rfds); 722 max_fd = max(max_fd, max_fd_added); 723 724 for (auto& notifier : *s_notifiers) { 725 if (notifier->event_mask() & Notifier::Read) 726 add_fd_to_set(notifier->fd(), rfds); 727 if (notifier->event_mask() & Notifier::Write) 728 add_fd_to_set(notifier->fd(), wfds); 729 if (notifier->event_mask() & Notifier::Exceptional) 730 VERIFY_NOT_REACHED(); 731 } 732 733 bool queued_events_is_empty; 734 { 735 Threading::MutexLocker locker(m_private->lock); 736 queued_events_is_empty = m_queued_events.is_empty(); 737 } 738 739 // Figure out how long to wait at maximum. 740 // This mainly depends on the WaitMode and whether we have pending events, but also the next expiring timer. 741 Time now; 742 struct timeval timeout = { 0, 0 }; 743 bool should_wait_forever = false; 744 if (mode == WaitMode::WaitForEvents && queued_events_is_empty) { 745 auto next_timer_expiration = get_next_timer_expiration(); 746 if (next_timer_expiration.has_value()) { 747 now = Time::now_monotonic_coarse(); 748 auto computed_timeout = next_timer_expiration.value() - now; 749 if (computed_timeout.is_negative()) 750 computed_timeout = Time::zero(); 751 timeout = computed_timeout.to_timeval(); 752 } else { 753 should_wait_forever = true; 754 } 755 } 756 757try_select_again: 758 // select() and wait for file system events, calls to wake(), POSIX signals, or timer expirations. 759 int marked_fd_count = select(max_fd + 1, &rfds, &wfds, nullptr, should_wait_forever ? nullptr : &timeout); 760 // Because POSIX, we might spuriously return from select() with EINTR; just select again. 761 if (marked_fd_count < 0) { 762 int saved_errno = errno; 763 if (saved_errno == EINTR) { 764 if (m_exit_requested) 765 return; 766 goto try_select_again; 767 } 768 dbgln("Core::EventLoop::wait_for_event: {} ({}: {})", marked_fd_count, saved_errno, strerror(saved_errno)); 769 VERIFY_NOT_REACHED(); 770 } 771 772 // We woke up due to a call to wake() or a POSIX signal. 773 // Handle signals and see whether we need to handle events as well. 774 if (FD_ISSET(s_wake_pipe_fds[0], &rfds)) { 775 int wake_events[8]; 776 ssize_t nread; 777 // We might receive another signal while read()ing here. The signal will go to the handle_signal properly, 778 // but we get interrupted. Therefore, just retry while we were interrupted. 779 do { 780 errno = 0; 781 nread = read(s_wake_pipe_fds[0], wake_events, sizeof(wake_events)); 782 if (nread == 0) 783 break; 784 } while (nread < 0 && errno == EINTR); 785 if (nread < 0) { 786 perror("Core::EventLoop::wait_for_event: read from wake pipe"); 787 VERIFY_NOT_REACHED(); 788 } 789 VERIFY(nread > 0); 790 bool wake_requested = false; 791 int event_count = nread / sizeof(wake_events[0]); 792 for (int i = 0; i < event_count; i++) { 793 if (wake_events[i] != 0) 794 dispatch_signal(wake_events[i]); 795 else 796 wake_requested = true; 797 } 798 799 if (!wake_requested && nread == sizeof(wake_events)) 800 goto retry; 801 } 802 803 if (!s_timers->is_empty()) { 804 now = Time::now_monotonic_coarse(); 805 } 806 807 // Handle expired timers. 808 for (auto& it : *s_timers) { 809 auto& timer = *it.value; 810 if (!timer.has_expired(now)) 811 continue; 812 auto owner = timer.owner.strong_ref(); 813 if (timer.fire_when_not_visible == TimerShouldFireWhenNotVisible::No 814 && owner && !owner->is_visible_for_timer_purposes()) { 815 continue; 816 } 817 818 dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop: Timer {} has expired, sending Core::TimerEvent to {}", timer.timer_id, *owner); 819 820 if (owner) 821 post_event(*owner, make<TimerEvent>(timer.timer_id)); 822 if (timer.should_reload) { 823 timer.reload(now); 824 } else { 825 // FIXME: Support removing expired timers that don't want to reload. 826 VERIFY_NOT_REACHED(); 827 } 828 } 829 830 if (!marked_fd_count) 831 return; 832 833 // Handle file system notifiers by making them normal events. 834 for (auto& notifier : *s_notifiers) { 835 if (FD_ISSET(notifier->fd(), &rfds)) { 836 if (notifier->event_mask() & Notifier::Event::Read) 837 post_event(*notifier, make<NotifierReadEvent>(notifier->fd())); 838 } 839 if (FD_ISSET(notifier->fd(), &wfds)) { 840 if (notifier->event_mask() & Notifier::Event::Write) 841 post_event(*notifier, make<NotifierWriteEvent>(notifier->fd())); 842 } 843 } 844} 845 846bool EventLoopTimer::has_expired(Time const& now) const 847{ 848 return now > fire_time; 849} 850 851void EventLoopTimer::reload(Time const& now) 852{ 853 fire_time = now + interval; 854} 855 856Optional<Time> EventLoop::get_next_timer_expiration() 857{ 858 auto now = Time::now_monotonic_coarse(); 859 Optional<Time> soonest {}; 860 for (auto& it : *s_timers) { 861 auto& fire_time = it.value->fire_time; 862 auto owner = it.value->owner.strong_ref(); 863 if (it.value->fire_when_not_visible == TimerShouldFireWhenNotVisible::No 864 && owner && !owner->is_visible_for_timer_purposes()) { 865 continue; 866 } 867 // OPTIMIZATION: If we have a timer that needs to fire right away, we can stop looking here. 868 // FIXME: This whole operation could be O(1) with a better data structure. 869 if (fire_time < now) 870 return now; 871 if (!soonest.has_value() || fire_time < soonest.value()) 872 soonest = fire_time; 873 } 874 return soonest; 875} 876 877int EventLoop::register_timer(Object& object, int milliseconds, bool should_reload, TimerShouldFireWhenNotVisible fire_when_not_visible) 878{ 879 VERIFY_EVENT_LOOP_INITIALIZED(); 880 VERIFY(milliseconds >= 0); 881 auto timer = make<EventLoopTimer>(); 882 timer->owner = object; 883 timer->interval = Time::from_milliseconds(milliseconds); 884 timer->reload(Time::now_monotonic_coarse()); 885 timer->should_reload = should_reload; 886 timer->fire_when_not_visible = fire_when_not_visible; 887 int timer_id = s_id_allocator.with_locked([](auto& allocator) { return allocator->allocate(); }); 888 timer->timer_id = timer_id; 889 s_timers->set(timer_id, move(timer)); 890 return timer_id; 891} 892 893bool EventLoop::unregister_timer(int timer_id) 894{ 895 VERIFY_EVENT_LOOP_INITIALIZED(); 896 s_id_allocator.with_locked([&](auto& allocator) { allocator->deallocate(timer_id); }); 897 auto it = s_timers->find(timer_id); 898 if (it == s_timers->end()) 899 return false; 900 s_timers->remove(it); 901 return true; 902} 903 904void EventLoop::register_notifier(Badge<Notifier>, Notifier& notifier) 905{ 906 VERIFY_EVENT_LOOP_INITIALIZED(); 907 s_notifiers->set(&notifier); 908} 909 910void EventLoop::unregister_notifier(Badge<Notifier>, Notifier& notifier) 911{ 912 VERIFY_EVENT_LOOP_INITIALIZED(); 913 s_notifiers->remove(&notifier); 914} 915 916void EventLoop::wake_current() 917{ 918 EventLoop::current().wake(); 919} 920 921void EventLoop::wake() 922{ 923 dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop::wake()"); 924 int wake_event = 0; 925 int nwritten = write((*m_wake_pipe_fds)[1], &wake_event, sizeof(wake_event)); 926 if (nwritten < 0) { 927 perror("EventLoop::wake: write"); 928 VERIFY_NOT_REACHED(); 929 } 930} 931 932EventLoop::QueuedEvent::QueuedEvent(Object& receiver, NonnullOwnPtr<Event> event) 933 : receiver(receiver) 934 , event(move(event)) 935{ 936} 937 938EventLoop::QueuedEvent::QueuedEvent(QueuedEvent&& other) 939 : receiver(other.receiver) 940 , event(move(other.event)) 941{ 942} 943 944}