Coverage Report

Created: 2022-01-18 06:27

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Host/MainLoop.h
Line
Count
Source
1
//===-- MainLoop.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_MAINLOOP_H
10
#define LLDB_HOST_MAINLOOP_H
11
12
#include "lldb/Host/Config.h"
13
#include "lldb/Host/MainLoopBase.h"
14
#include "llvm/ADT/DenseMap.h"
15
#include <csignal>
16
#include <list>
17
18
#if !HAVE_PPOLL && !HAVE_SYS_EVENT_H && !defined(__ANDROID__)
19
#define SIGNAL_POLLING_UNSUPPORTED 1
20
#endif
21
22
namespace lldb_private {
23
24
// Implementation of the MainLoopBase class. It can monitor file descriptors
25
// for readability using ppoll, kqueue, poll or WSAPoll. On Windows it only
26
// supports polling sockets, and will not work on generic file handles or
27
// pipes. On systems without kqueue or ppoll handling singnals is not
28
// supported. In addition to the common base, this class provides the ability
29
// to invoke a given handler when a signal is received.
30
//
31
// Since this class is primarily intended to be used for single-threaded
32
// processing, it does not attempt to perform any internal synchronisation and
33
// any concurrent accesses must be protected  externally. However, it is
34
// perfectly legitimate to have more than one instance of this class running on
35
// separate threads, or even a single thread (with some limitations on signal
36
// monitoring).
37
// TODO: Add locking if this class is to be used in a multi-threaded context.
38
class MainLoop : public MainLoopBase {
39
private:
40
  class SignalHandle;
41
42
public:
43
  typedef std::unique_ptr<SignalHandle> SignalHandleUP;
44
45
  MainLoop();
46
  ~MainLoop() override;
47
48
  ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp,
49
                                  const Callback &callback,
50
                                  Status &error) override;
51
52
  // Listening for signals from multiple MainLoop instances is perfectly safe
53
  // as long as they don't try to listen for the same signal. The callback
54
  // function is invoked when the control returns to the Run() function, not
55
  // when the hander is executed. This mean that you can treat the callback as
56
  // a normal function and perform things which would not be safe in a signal
57
  // handler. However, since the callback is not invoked synchronously, you
58
  // cannot use this mechanism to handle SIGSEGV and the like.
59
  SignalHandleUP RegisterSignal(int signo, const Callback &callback,
60
                                Status &error);
61
62
  Status Run() override;
63
64
  // This should only be performed from a callback. Do not attempt to terminate
65
  // the processing from another thread.
66
  // TODO: Add synchronization if we want to be terminated from another thread.
67
52
  void RequestTermination() override { m_terminate_request = true; }
68
69
protected:
70
  void UnregisterReadObject(IOObject::WaitableHandle handle) override;
71
72
  void UnregisterSignal(int signo, std::list<Callback>::iterator callback_it);
73
74
private:
75
  void ProcessReadObject(IOObject::WaitableHandle handle);
76
  void ProcessSignal(int signo);
77
78
  class SignalHandle {
79
  public:
80
9
    ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo, m_callback_it); }
81
82
  private:
83
    SignalHandle(MainLoop &mainloop, int signo,
84
                 std::list<Callback>::iterator callback_it)
85
9
        : m_mainloop(mainloop), m_signo(signo), m_callback_it(callback_it) {}
86
87
    MainLoop &m_mainloop;
88
    int m_signo;
89
    std::list<Callback>::iterator m_callback_it;
90
91
    friend class MainLoop;
92
    SignalHandle(const SignalHandle &) = delete;
93
    const SignalHandle &operator=(const SignalHandle &) = delete;
94
  };
95
96
  struct SignalInfo {
97
    std::list<Callback> callbacks;
98
#ifndef SIGNAL_POLLING_UNSUPPORTED
99
    struct sigaction old_action;
100
#endif
101
    bool was_blocked : 1;
102
  };
103
  class RunImpl;
104
105
  llvm::DenseMap<IOObject::WaitableHandle, Callback> m_read_fds;
106
  llvm::DenseMap<int, SignalInfo> m_signals;
107
#if HAVE_SYS_EVENT_H
108
  int m_kqueue;
109
#endif
110
  bool m_terminate_request : 1;
111
};
112
113
} // namespace lldb_private
114
115
#endif // LLDB_HOST_MAINLOOP_H