30 Watchdog::Watchdog(v8::Isolate* isolate, uint64_t ms,
bool* timed_out)
31 : isolate_(isolate), timed_out_(timed_out) {
34 loop_ =
new uv_loop_t;
36 rc = uv_loop_init(loop_);
39 "Failed to initialize uv loop.");
42 rc = uv_async_init(loop_, &async_, &Watchdog::Async);
45 rc = uv_timer_init(loop_, &timer_);
48 rc = uv_timer_start(&timer_, &Watchdog::Timer, ms, 0);
51 rc = uv_thread_create(&thread_, &Watchdog::Run,
this);
56 Watchdog::~Watchdog() {
57 uv_async_send(&async_);
58 uv_thread_join(&thread_);
60 uv_close(reinterpret_cast<uv_handle_t*>(&async_),
nullptr);
63 uv_run(loop_, UV_RUN_DEFAULT);
65 int rc = uv_loop_close(loop_);
72 void Watchdog::Run(
void* arg) {
73 Watchdog* wd =
static_cast<Watchdog*
>(arg);
77 uv_run(wd->loop_, UV_RUN_DEFAULT);
81 uv_close(reinterpret_cast<uv_handle_t*>(&wd->timer_),
nullptr);
85 void Watchdog::Async(uv_async_t* async) {
86 Watchdog* w = ContainerOf(&Watchdog::async_, async);
91 void Watchdog::Timer(uv_timer_t* timer) {
92 Watchdog* w = ContainerOf(&Watchdog::timer_, timer);
93 *w->timed_out_ =
true;
94 w->isolate()->TerminateExecution();
99 SigintWatchdog::SigintWatchdog(
100 v8::Isolate* isolate,
bool* received_signal)
101 : isolate_(isolate), received_signal_(received_signal) {
103 SigintWatchdogHelper::GetInstance()->Register(
this);
105 SigintWatchdogHelper::GetInstance()->Start();
109 SigintWatchdog::~SigintWatchdog() {
110 SigintWatchdogHelper::GetInstance()->Unregister(
this);
111 SigintWatchdogHelper::GetInstance()->Stop();
115 void SigintWatchdog::HandleSigint() {
116 *received_signal_ =
true;
117 isolate_->TerminateExecution();
121 void* SigintWatchdogHelper::RunSigintWatchdog(
void* arg) {
126 uv_sem_wait(&instance.sem_);
127 is_stopping = InformWatchdogsAboutSignal();
128 }
while (!is_stopping);
134 void SigintWatchdogHelper::HandleSignal(
int signum) {
135 uv_sem_post(&instance.sem_);
142 BOOL WINAPI SigintWatchdogHelper::WinCtrlCHandlerRoutine(DWORD dwCtrlType) {
143 if (!instance.watchdog_disabled_ &&
144 (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT)) {
145 InformWatchdogsAboutSignal();
156 bool SigintWatchdogHelper::InformWatchdogsAboutSignal() {
157 Mutex::ScopedLock list_lock(instance.list_mutex_);
159 bool is_stopping =
false;
161 is_stopping = instance.stopping_;
166 if (instance.watchdogs_.empty() && !is_stopping) {
167 instance.has_pending_signal_ =
true;
170 for (
auto it : instance.watchdogs_)
178 Mutex::ScopedLock lock(mutex_);
180 if (start_stop_count_++ > 0) {
185 CHECK_EQ(has_running_thread_,
false);
186 has_pending_signal_ =
false;
190 sigfillset(&sigmask);
191 CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sigmask, &sigmask));
192 int ret = pthread_create(&thread_,
nullptr, RunSigintWatchdog,
nullptr);
193 CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sigmask,
nullptr));
197 has_running_thread_ =
true;
199 RegisterSignalHandler(SIGINT, HandleSignal);
201 if (watchdog_disabled_) {
202 watchdog_disabled_ =
false;
204 SetConsoleCtrlHandler(WinCtrlCHandlerRoutine, TRUE);
212 bool SigintWatchdogHelper::Stop() {
213 bool had_pending_signal;
214 Mutex::ScopedLock lock(mutex_);
217 Mutex::ScopedLock list_lock(list_mutex_);
219 had_pending_signal = has_pending_signal_;
221 if (--start_stop_count_ > 0) {
222 has_pending_signal_ =
false;
223 return had_pending_signal;
235 if (!has_running_thread_) {
236 has_pending_signal_ =
false;
237 return had_pending_signal;
244 CHECK_EQ(0, pthread_join(thread_,
nullptr));
245 has_running_thread_ =
false;
247 RegisterSignalHandler(SIGINT,
SignalExit,
true);
249 watchdog_disabled_ =
true;
252 had_pending_signal = has_pending_signal_;
253 has_pending_signal_ =
false;
255 return had_pending_signal;
259 bool SigintWatchdogHelper::HasPendingSignal() {
260 Mutex::ScopedLock lock(list_mutex_);
262 return has_pending_signal_;
266 void SigintWatchdogHelper::Register(SigintWatchdog* wd) {
267 Mutex::ScopedLock lock(list_mutex_);
269 watchdogs_.push_back(wd);
273 void SigintWatchdogHelper::Unregister(SigintWatchdog* wd) {
274 Mutex::ScopedLock lock(list_mutex_);
276 auto it = std::find(watchdogs_.begin(), watchdogs_.end(), wd);
278 CHECK_NE(it, watchdogs_.end());
279 watchdogs_.erase(it);
283 SigintWatchdogHelper::SigintWatchdogHelper()
284 : start_stop_count_(0),
285 has_pending_signal_(false) {
287 has_running_thread_ =
false;
289 CHECK_EQ(0, uv_sem_init(&sem_, 0));
291 watchdog_disabled_ =
false;
296 SigintWatchdogHelper::~SigintWatchdogHelper() {
297 start_stop_count_ = 0;
301 CHECK_EQ(has_running_thread_,
false);
302 uv_sem_destroy(&sem_);
306 SigintWatchdogHelper SigintWatchdogHelper::instance;
NO_RETURN void FatalError(const char *location, const char *message)
void SignalExit(int signo)
int Start(Isolate *isolate, IsolateData *isolate_data, int argc, const char *const *argv, int exec_argc, const char *const *exec_argv)