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
21namespace 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.
27class MainLoopPosix : public MainLoopBase {
28private:
29 class SignalHandle;
30
31public:
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
53protected:
54 void UnregisterReadObject(IOObject::WaitableHandle handle) override;
55 void UnregisterSignal(int signo, std::list<Callback>::iterator callback_it);
56
57 void TriggerPendingCallbacks() override;
58
59private:
60 void ProcessReadObject(IOObject::WaitableHandle handle);
61 void ProcessSignal(int signo);
62
63 class SignalHandle {
64 public:
65 ~SignalHandle() { m_mainloop.UnregisterSignal(signo: m_signo, callback_it: m_callback_it); }
66
67 private:
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

source code of lldb/include/lldb/Host/posix/MainLoopPosix.h