Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:48

0001 //===-- MainLoopPosix.h -----------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLDB_HOST_POSIX_MAINLOOPPOSIX_H
0010 #define LLDB_HOST_POSIX_MAINLOOPPOSIX_H
0011 
0012 #include "lldb/Host/Config.h"
0013 #include "lldb/Host/MainLoopBase.h"
0014 #include "lldb/Host/Pipe.h"
0015 #include "llvm/ADT/DenseMap.h"
0016 #include <atomic>
0017 #include <csignal>
0018 #include <list>
0019 #include <vector>
0020 
0021 namespace lldb_private {
0022 
0023 // Implementation of the MainLoopBase class. It can monitor file descriptors for
0024 // readability using ppoll, kqueue, or pselect. In addition to the common base,
0025 // this class provides the ability to invoke a given handler when a signal is
0026 // received.
0027 class MainLoopPosix : public MainLoopBase {
0028 private:
0029   class SignalHandle;
0030 
0031 public:
0032   typedef std::unique_ptr<SignalHandle> SignalHandleUP;
0033 
0034   MainLoopPosix();
0035   ~MainLoopPosix() override;
0036 
0037   ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp,
0038                                   const Callback &callback,
0039                                   Status &error) override;
0040 
0041   // Listening for signals from multiple MainLoop instances is perfectly safe
0042   // as long as they don't try to listen for the same signal. The callback
0043   // function is invoked when the control returns to the Run() function, not
0044   // when the hander is executed. This mean that you can treat the callback as
0045   // a normal function and perform things which would not be safe in a signal
0046   // handler. However, since the callback is not invoked synchronously, you
0047   // cannot use this mechanism to handle SIGSEGV and the like.
0048   SignalHandleUP RegisterSignal(int signo, const Callback &callback,
0049                                 Status &error);
0050 
0051   Status Run() override;
0052 
0053 protected:
0054   void UnregisterReadObject(IOObject::WaitableHandle handle) override;
0055   void UnregisterSignal(int signo, std::list<Callback>::iterator callback_it);
0056 
0057   void Interrupt() override;
0058 
0059 private:
0060   void ProcessReadObject(IOObject::WaitableHandle handle);
0061   void ProcessSignal(int signo);
0062   void ProcessSignals();
0063 
0064   class SignalHandle {
0065   public:
0066     ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo, m_callback_it); }
0067 
0068   private:
0069     SignalHandle(MainLoopPosix &mainloop, int signo,
0070                  std::list<Callback>::iterator callback_it)
0071         : m_mainloop(mainloop), m_signo(signo), m_callback_it(callback_it) {}
0072 
0073     MainLoopPosix &m_mainloop;
0074     int m_signo;
0075     std::list<Callback>::iterator m_callback_it;
0076 
0077     friend class MainLoopPosix;
0078     SignalHandle(const SignalHandle &) = delete;
0079     const SignalHandle &operator=(const SignalHandle &) = delete;
0080   };
0081 
0082   struct SignalInfo {
0083     std::list<Callback> callbacks;
0084     struct sigaction old_action;
0085     bool was_blocked : 1;
0086   };
0087   class RunImpl;
0088 
0089   llvm::DenseMap<IOObject::WaitableHandle, Callback> m_read_fds;
0090   llvm::DenseMap<int, SignalInfo> m_signals;
0091   Pipe m_interrupt_pipe;
0092   std::atomic<bool> m_interrupting = false;
0093 #if HAVE_SYS_EVENT_H
0094   int m_kqueue;
0095 #endif
0096 };
0097 
0098 } // namespace lldb_private
0099 
0100 #endif // LLDB_HOST_POSIX_MAINLOOPPOSIX_H