1 //===-- MainLoopPosix.h -----------------------------------------*- C++ -*-===// 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 #ifndef LLDB_HOST_POSIX_MAINLOOPPOSIX_H 10 #define LLDB_HOST_POSIX_MAINLOOPPOSIX_H 11 12 #include "lldb/Host/Config.h" 13 #include "lldb/Host/MainLoopBase.h" 14 #include "lldb/Host/Pipe.h" 15 #include "llvm/ADT/DenseMap.h" 16 #include <atomic> 17 #include <csignal> 18 #include <list> 19 #include <vector> 20 21 namespace lldb_private { 22 23 // Implementation of the MainLoopBase class. It can monitor file descriptors for 24 // readability using ppoll, kqueue, or pselect. In addition to the common base, 25 // this class provides the ability to invoke a given handler when a signal is 26 // received. 27 class MainLoopPosix : public MainLoopBase { 28 private: 29 class SignalHandle; 30 31 public: 32 typedef std::unique_ptr<SignalHandle> SignalHandleUP; 33 34 MainLoopPosix(); 35 ~MainLoopPosix() override; 36 37 ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp, 38 const Callback &callback, 39 Status &error) override; 40 41 // Listening for signals from multiple MainLoop instances is perfectly safe 42 // as long as they don't try to listen for the same signal. The callback 43 // function is invoked when the control returns to the Run() function, not 44 // when the hander is executed. This mean that you can treat the callback as 45 // a normal function and perform things which would not be safe in a signal 46 // handler. However, since the callback is not invoked synchronously, you 47 // cannot use this mechanism to handle SIGSEGV and the like. 48 SignalHandleUP RegisterSignal(int signo, const Callback &callback, 49 Status &error); 50 51 Status Run() override; 52 53 protected: 54 void UnregisterReadObject(IOObject::WaitableHandle handle) override; 55 void UnregisterSignal(int signo, std::list<Callback>::iterator callback_it); 56 57 void TriggerPendingCallbacks() override; 58 59 private: 60 void ProcessReadObject(IOObject::WaitableHandle handle); 61 void ProcessSignal(int signo); 62 63 class SignalHandle { 64 public: ~SignalHandle()65 ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo, m_callback_it); } 66 67 private: SignalHandle(MainLoopPosix & mainloop,int signo,std::list<Callback>::iterator callback_it)68 SignalHandle(MainLoopPosix &mainloop, int signo, 69 std::list<Callback>::iterator callback_it) 70 : m_mainloop(mainloop), m_signo(signo), m_callback_it(callback_it) {} 71 72 MainLoopPosix &m_mainloop; 73 int m_signo; 74 std::list<Callback>::iterator m_callback_it; 75 76 friend class MainLoopPosix; 77 SignalHandle(const SignalHandle &) = delete; 78 const SignalHandle &operator=(const SignalHandle &) = delete; 79 }; 80 81 struct SignalInfo { 82 std::list<Callback> callbacks; 83 struct sigaction old_action; 84 bool was_blocked : 1; 85 }; 86 class RunImpl; 87 88 llvm::DenseMap<IOObject::WaitableHandle, Callback> m_read_fds; 89 llvm::DenseMap<int, SignalInfo> m_signals; 90 Pipe m_trigger_pipe; 91 std::atomic<bool> m_triggering; 92 #if HAVE_SYS_EVENT_H 93 int m_kqueue; 94 #endif 95 }; 96 97 } // namespace lldb_private 98 99 #endif // LLDB_HOST_POSIX_MAINLOOPPOSIX_H 100