11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors.
21cb0ef41Sopenharmony_ci//
31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a
41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the
51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including
61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish,
71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit
81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the
91cb0ef41Sopenharmony_ci// following conditions:
101cb0ef41Sopenharmony_ci//
111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included
121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software.
131cb0ef41Sopenharmony_ci//
141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE.
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#ifndef SRC_NODE_WATCHDOG_H_
231cb0ef41Sopenharmony_ci#define SRC_NODE_WATCHDOG_H_
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci#include <vector>
281cb0ef41Sopenharmony_ci#include "handle_wrap.h"
291cb0ef41Sopenharmony_ci#include "memory_tracker-inl.h"
301cb0ef41Sopenharmony_ci#include "node_mutex.h"
311cb0ef41Sopenharmony_ci#include "uv.h"
321cb0ef41Sopenharmony_ci#include "v8.h"
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci#ifdef __POSIX__
351cb0ef41Sopenharmony_ci#include <pthread.h>
361cb0ef41Sopenharmony_ci#endif
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_cinamespace node {
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_cienum class SignalPropagation {
411cb0ef41Sopenharmony_ci  kContinuePropagation,
421cb0ef41Sopenharmony_ci  kStopPropagation,
431cb0ef41Sopenharmony_ci};
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ciclass Watchdog {
461cb0ef41Sopenharmony_ci public:
471cb0ef41Sopenharmony_ci  explicit Watchdog(v8::Isolate* isolate,
481cb0ef41Sopenharmony_ci                    uint64_t ms,
491cb0ef41Sopenharmony_ci                    bool* timed_out = nullptr);
501cb0ef41Sopenharmony_ci  ~Watchdog();
511cb0ef41Sopenharmony_ci  v8::Isolate* isolate() { return isolate_; }
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci private:
541cb0ef41Sopenharmony_ci  static void Run(void* arg);
551cb0ef41Sopenharmony_ci  static void Timer(uv_timer_t* timer);
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  v8::Isolate* isolate_;
581cb0ef41Sopenharmony_ci  uv_thread_t thread_;
591cb0ef41Sopenharmony_ci  uv_loop_t loop_;
601cb0ef41Sopenharmony_ci  uv_async_t async_;
611cb0ef41Sopenharmony_ci  uv_timer_t timer_;
621cb0ef41Sopenharmony_ci  bool* timed_out_;
631cb0ef41Sopenharmony_ci};
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ciclass SigintWatchdogBase {
661cb0ef41Sopenharmony_ci public:
671cb0ef41Sopenharmony_ci  virtual ~SigintWatchdogBase() = default;
681cb0ef41Sopenharmony_ci  virtual SignalPropagation HandleSigint() = 0;
691cb0ef41Sopenharmony_ci};
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ciclass SigintWatchdog : public SigintWatchdogBase {
721cb0ef41Sopenharmony_ci public:
731cb0ef41Sopenharmony_ci  explicit SigintWatchdog(v8::Isolate* isolate,
741cb0ef41Sopenharmony_ci                          bool* received_signal = nullptr);
751cb0ef41Sopenharmony_ci  ~SigintWatchdog();
761cb0ef41Sopenharmony_ci  v8::Isolate* isolate() { return isolate_; }
771cb0ef41Sopenharmony_ci  SignalPropagation HandleSigint() override;
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci private:
801cb0ef41Sopenharmony_ci  v8::Isolate* isolate_;
811cb0ef41Sopenharmony_ci  bool* received_signal_;
821cb0ef41Sopenharmony_ci};
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ciclass TraceSigintWatchdog : public HandleWrap, public SigintWatchdogBase {
851cb0ef41Sopenharmony_ci public:
861cb0ef41Sopenharmony_ci  static void Init(Environment* env, v8::Local<v8::Object> target);
871cb0ef41Sopenharmony_ci  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
881cb0ef41Sopenharmony_ci  static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
891cb0ef41Sopenharmony_ci  static void Stop(const v8::FunctionCallbackInfo<v8::Value>& args);
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  SignalPropagation HandleSigint() override;
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  inline void MemoryInfo(node::MemoryTracker* tracker) const override {
941cb0ef41Sopenharmony_ci    tracker->TrackInlineField("handle_", handle_);
951cb0ef41Sopenharmony_ci  }
961cb0ef41Sopenharmony_ci  SET_MEMORY_INFO_NAME(TraceSigintWatchdog)
971cb0ef41Sopenharmony_ci  SET_SELF_SIZE(TraceSigintWatchdog)
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci private:
1001cb0ef41Sopenharmony_ci  enum class SignalFlags { None, FromIdle, FromInterrupt };
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  TraceSigintWatchdog(Environment* env, v8::Local<v8::Object> object);
1031cb0ef41Sopenharmony_ci  void HandleInterrupt();
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  bool interrupting = false;
1061cb0ef41Sopenharmony_ci  uv_async_t handle_;
1071cb0ef41Sopenharmony_ci  SignalFlags signal_flag_ = SignalFlags::None;
1081cb0ef41Sopenharmony_ci};
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ciclass SigintWatchdogHelper {
1111cb0ef41Sopenharmony_ci public:
1121cb0ef41Sopenharmony_ci  static SigintWatchdogHelper* GetInstance() { return &instance; }
1131cb0ef41Sopenharmony_ci  static Mutex& GetInstanceActionMutex() { return instance_action_mutex_; }
1141cb0ef41Sopenharmony_ci  void Register(SigintWatchdogBase* watchdog);
1151cb0ef41Sopenharmony_ci  void Unregister(SigintWatchdogBase* watchdog);
1161cb0ef41Sopenharmony_ci  bool HasPendingSignal();
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci  int Start();
1191cb0ef41Sopenharmony_ci  bool Stop();
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci private:
1221cb0ef41Sopenharmony_ci  SigintWatchdogHelper();
1231cb0ef41Sopenharmony_ci  ~SigintWatchdogHelper();
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  static bool InformWatchdogsAboutSignal();
1261cb0ef41Sopenharmony_ci  static SigintWatchdogHelper instance;
1271cb0ef41Sopenharmony_ci  static Mutex instance_action_mutex_;
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci  int start_stop_count_;
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  Mutex mutex_;
1321cb0ef41Sopenharmony_ci  Mutex list_mutex_;
1331cb0ef41Sopenharmony_ci  std::vector<SigintWatchdogBase*> watchdogs_;
1341cb0ef41Sopenharmony_ci  bool has_pending_signal_;
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci#ifdef __POSIX__
1371cb0ef41Sopenharmony_ci  pthread_t thread_;
1381cb0ef41Sopenharmony_ci  uv_sem_t sem_;
1391cb0ef41Sopenharmony_ci  bool has_running_thread_;
1401cb0ef41Sopenharmony_ci  bool stopping_;
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  static void* RunSigintWatchdog(void* arg);
1431cb0ef41Sopenharmony_ci  static void HandleSignal(int signum, siginfo_t* info, void* ucontext);
1441cb0ef41Sopenharmony_ci#else
1451cb0ef41Sopenharmony_ci  bool watchdog_disabled_;
1461cb0ef41Sopenharmony_ci  static BOOL WINAPI WinCtrlCHandlerRoutine(DWORD dwCtrlType);
1471cb0ef41Sopenharmony_ci#endif
1481cb0ef41Sopenharmony_ci};
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci}  // namespace node
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci#endif  // SRC_NODE_WATCHDOG_H_
155