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