/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Host/posix/MainLoopPosix.h
Line | Count | Source |
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: |
65 | 9 | ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo, m_callback_it); } |
66 | | |
67 | | private: |
68 | | SignalHandle(MainLoopPosix &mainloop, int signo, |
69 | | std::list<Callback>::iterator callback_it) |
70 | 9 | : 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 |