xref: /third_party/node/src/node_watchdog.h (revision 1cb0ef41)
1// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22#ifndef SRC_NODE_WATCHDOG_H_
23#define SRC_NODE_WATCHDOG_H_
24
25#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
26
27#include <vector>
28#include "handle_wrap.h"
29#include "memory_tracker-inl.h"
30#include "node_mutex.h"
31#include "uv.h"
32#include "v8.h"
33
34#ifdef __POSIX__
35#include <pthread.h>
36#endif
37
38namespace node {
39
40enum class SignalPropagation {
41  kContinuePropagation,
42  kStopPropagation,
43};
44
45class Watchdog {
46 public:
47  explicit Watchdog(v8::Isolate* isolate,
48                    uint64_t ms,
49                    bool* timed_out = nullptr);
50  ~Watchdog();
51  v8::Isolate* isolate() { return isolate_; }
52
53 private:
54  static void Run(void* arg);
55  static void Timer(uv_timer_t* timer);
56
57  v8::Isolate* isolate_;
58  uv_thread_t thread_;
59  uv_loop_t loop_;
60  uv_async_t async_;
61  uv_timer_t timer_;
62  bool* timed_out_;
63};
64
65class SigintWatchdogBase {
66 public:
67  virtual ~SigintWatchdogBase() = default;
68  virtual SignalPropagation HandleSigint() = 0;
69};
70
71class SigintWatchdog : public SigintWatchdogBase {
72 public:
73  explicit SigintWatchdog(v8::Isolate* isolate,
74                          bool* received_signal = nullptr);
75  ~SigintWatchdog();
76  v8::Isolate* isolate() { return isolate_; }
77  SignalPropagation HandleSigint() override;
78
79 private:
80  v8::Isolate* isolate_;
81  bool* received_signal_;
82};
83
84class TraceSigintWatchdog : public HandleWrap, public SigintWatchdogBase {
85 public:
86  static void Init(Environment* env, v8::Local<v8::Object> target);
87  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
88  static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
89  static void Stop(const v8::FunctionCallbackInfo<v8::Value>& args);
90
91  SignalPropagation HandleSigint() override;
92
93  inline void MemoryInfo(node::MemoryTracker* tracker) const override {
94    tracker->TrackInlineField("handle_", handle_);
95  }
96  SET_MEMORY_INFO_NAME(TraceSigintWatchdog)
97  SET_SELF_SIZE(TraceSigintWatchdog)
98
99 private:
100  enum class SignalFlags { None, FromIdle, FromInterrupt };
101
102  TraceSigintWatchdog(Environment* env, v8::Local<v8::Object> object);
103  void HandleInterrupt();
104
105  bool interrupting = false;
106  uv_async_t handle_;
107  SignalFlags signal_flag_ = SignalFlags::None;
108};
109
110class SigintWatchdogHelper {
111 public:
112  static SigintWatchdogHelper* GetInstance() { return &instance; }
113  static Mutex& GetInstanceActionMutex() { return instance_action_mutex_; }
114  void Register(SigintWatchdogBase* watchdog);
115  void Unregister(SigintWatchdogBase* watchdog);
116  bool HasPendingSignal();
117
118  int Start();
119  bool Stop();
120
121 private:
122  SigintWatchdogHelper();
123  ~SigintWatchdogHelper();
124
125  static bool InformWatchdogsAboutSignal();
126  static SigintWatchdogHelper instance;
127  static Mutex instance_action_mutex_;
128
129  int start_stop_count_;
130
131  Mutex mutex_;
132  Mutex list_mutex_;
133  std::vector<SigintWatchdogBase*> watchdogs_;
134  bool has_pending_signal_;
135
136#ifdef __POSIX__
137  pthread_t thread_;
138  uv_sem_t sem_;
139  bool has_running_thread_;
140  bool stopping_;
141
142  static void* RunSigintWatchdog(void* arg);
143  static void HandleSignal(int signum, siginfo_t* info, void* ucontext);
144#else
145  bool watchdog_disabled_;
146  static BOOL WINAPI WinCtrlCHandlerRoutine(DWORD dwCtrlType);
147#endif
148};
149
150}  // namespace node
151
152#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
153
154#endif  // SRC_NODE_WATCHDOG_H_
155