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 38 namespace node { 39 40 enum class SignalPropagation { 41 kContinuePropagation, 42 kStopPropagation, 43 }; 44 45 class Watchdog { 46 public: 47 explicit Watchdog(v8::Isolate* isolate, 48 uint64_t ms, 49 bool* timed_out = nullptr); 50 ~Watchdog(); isolate()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 65 class SigintWatchdogBase { 66 public: 67 virtual ~SigintWatchdogBase() = default; 68 virtual SignalPropagation HandleSigint() = 0; 69 }; 70 71 class SigintWatchdog : public SigintWatchdogBase { 72 public: 73 explicit SigintWatchdog(v8::Isolate* isolate, 74 bool* received_signal = nullptr); 75 ~SigintWatchdog(); isolate()76 v8::Isolate* isolate() { return isolate_; } 77 SignalPropagation HandleSigint() override; 78 79 private: 80 v8::Isolate* isolate_; 81 bool* received_signal_; 82 }; 83 84 class 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 MemoryInfo(node::MemoryTracker * tracker)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 110 class SigintWatchdogHelper { 111 public: GetInstance()112 static SigintWatchdogHelper* GetInstance() { return &instance; } 113 void Register(SigintWatchdogBase* watchdog); 114 void Unregister(SigintWatchdogBase* watchdog); 115 bool HasPendingSignal(); 116 117 int Start(); 118 bool Stop(); 119 120 private: 121 SigintWatchdogHelper(); 122 ~SigintWatchdogHelper(); 123 124 static bool InformWatchdogsAboutSignal(); 125 static SigintWatchdogHelper instance; 126 127 int start_stop_count_; 128 129 Mutex mutex_; 130 Mutex list_mutex_; 131 std::vector<SigintWatchdogBase*> watchdogs_; 132 bool has_pending_signal_; 133 134 #ifdef __POSIX__ 135 pthread_t thread_; 136 uv_sem_t sem_; 137 bool has_running_thread_; 138 bool stopping_; 139 140 static void* RunSigintWatchdog(void* arg); 141 static void HandleSignal(int signum, siginfo_t* info, void* ucontext); 142 #else 143 bool watchdog_disabled_; 144 static BOOL WINAPI WinCtrlCHandlerRoutine(DWORD dwCtrlType); 145 #endif 146 }; 147 148 } // namespace node 149 150 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 151 152 #endif // SRC_NODE_WATCHDOG_H_ 153