OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromecast/browser/cast_browser_main_parts.h" | 5 #include "chromecast/browser/cast_browser_main_parts.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 | 10 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
69 #if defined(USE_AURA) | 69 #if defined(USE_AURA) |
70 #include "chromecast/graphics/cast_screen.h" | 70 #include "chromecast/graphics/cast_screen.h" |
71 #include "ui/aura/env.h" | 71 #include "ui/aura/env.h" |
72 #include "ui/gfx/screen.h" | 72 #include "ui/gfx/screen.h" |
73 #endif | 73 #endif |
74 | 74 |
75 namespace { | 75 namespace { |
76 | 76 |
77 #if !defined(OS_ANDROID) | 77 #if !defined(OS_ANDROID) |
78 int kSignalsToRunClosure[] = { SIGTERM, SIGINT, }; | 78 int kSignalsToRunClosure[] = { SIGTERM, SIGINT, }; |
79 | |
80 // Closure to run on SIGTERM and SIGINT. | 79 // Closure to run on SIGTERM and SIGINT. |
81 base::Closure* g_signal_closure = NULL; | 80 base::Closure* g_signal_closure = NULL; |
81 base::PlatformThreadId g_main_thread_id; | |
82 int g_quit_signal = 0; | |
82 | 83 |
83 void RunClosureOnSignal(int signum) { | 84 void RunClosureOnSignal(int signum) { |
84 LOG(ERROR) << "Got signal " << signum; | 85 if (base::PlatformThread::CurrentId() != g_main_thread_id) |
maclellant
2015/12/28 19:30:32
This printing is still useful to detect the cases
kmackay
2015/12/29 18:23:01
Done.
| |
85 DCHECK(g_signal_closure); | 86 return; |
86 // Expect main thread got this signal. Otherwise, weak_ptr of run_loop will | 87 if (!g_signal_closure) |
87 // crash the process. | 88 return; |
89 g_quit_signal = signum; | |
88 g_signal_closure->Run(); | 90 g_signal_closure->Run(); |
89 } | 91 } |
90 | 92 |
91 void RegisterClosureOnSignal(const base::Closure& closure) { | 93 void RegisterClosureOnSignal(base::Closure* closure) { |
94 DCHECK(closure); | |
92 DCHECK(!g_signal_closure); | 95 DCHECK(!g_signal_closure); |
93 DCHECK_GT(arraysize(kSignalsToRunClosure), 0U); | 96 DCHECK_GT(arraysize(kSignalsToRunClosure), 0U); |
94 | 97 |
95 // Allow memory leak by intention. | 98 g_signal_closure = closure; |
96 g_signal_closure = new base::Closure(closure); | 99 g_main_thread_id = base::PlatformThread::CurrentId(); |
97 | 100 |
98 struct sigaction sa_new; | 101 struct sigaction sa_new; |
99 memset(&sa_new, 0, sizeof(sa_new)); | 102 memset(&sa_new, 0, sizeof(sa_new)); |
100 sa_new.sa_handler = RunClosureOnSignal; | 103 sa_new.sa_handler = RunClosureOnSignal; |
101 sigfillset(&sa_new.sa_mask); | 104 sigfillset(&sa_new.sa_mask); |
102 sa_new.sa_flags = SA_RESTART; | 105 sa_new.sa_flags = SA_RESTART; |
103 | 106 |
104 for (size_t i = 0; i < arraysize(kSignalsToRunClosure); i++) { | 107 for (int sig : kSignalsToRunClosure) { |
105 struct sigaction sa_old; | 108 struct sigaction sa_old; |
106 if (sigaction(kSignalsToRunClosure[i], &sa_new, &sa_old) == -1) { | 109 if (sigaction(sig, &sa_new, &sa_old) == -1) { |
107 NOTREACHED(); | 110 NOTREACHED(); |
108 } else { | 111 } else { |
109 DCHECK_EQ(sa_old.sa_handler, SIG_DFL); | 112 DCHECK_EQ(sa_old.sa_handler, SIG_DFL); |
maclellant
2015/12/28 19:30:32
Since old handler is never unregistered this will
kmackay
2015/12/29 18:23:01
I don't think so. Note that this check is not new
| |
110 } | 113 } |
111 } | 114 } |
112 | 115 |
113 // Get the first signal to exit when the parent process dies. | 116 // Get the first signal to exit when the parent process dies. |
114 prctl(PR_SET_PDEATHSIG, kSignalsToRunClosure[0]); | 117 prctl(PR_SET_PDEATHSIG, kSignalsToRunClosure[0]); |
115 } | 118 } |
116 | 119 |
120 void DeregisterClosureOnSignal(base::Closure* closure) { | |
121 DCHECK_EQ(g_signal_closure, closure); | |
122 DCHECK_EQ(g_main_thread_id, base::PlatformThread::CurrentId()); | |
123 g_signal_closure = nullptr; | |
maclellant
2015/12/28 19:30:32
Technically this is unsafe since the signal handle
kmackay
2015/12/29 18:23:01
Right, I think the previous code with the "memory
| |
124 } | |
125 | |
117 const int kKillOnAlarmTimeoutSec = 5; // 5 seconds | 126 const int kKillOnAlarmTimeoutSec = 5; // 5 seconds |
118 | 127 |
119 void KillOnAlarm(int signum) { | 128 void KillOnAlarm(int signum) { |
120 LOG(ERROR) << "Got alarm signal for termination: " << signum; | 129 LOG(ERROR) << "Got alarm signal for termination: " << signum; |
121 raise(SIGKILL); | 130 raise(SIGKILL); |
122 } | 131 } |
123 | 132 |
124 void RegisterKillOnAlarm(int timeout_seconds) { | 133 void RegisterKillOnAlarm(int timeout_seconds) { |
125 struct sigaction sa_new; | 134 struct sigaction sa_new; |
126 memset(&sa_new, 0, sizeof(sa_new)); | 135 memset(&sa_new, 0, sizeof(sa_new)); |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
385 } | 394 } |
386 | 395 |
387 bool CastBrowserMainParts::MainMessageLoopRun(int* result_code) { | 396 bool CastBrowserMainParts::MainMessageLoopRun(int* result_code) { |
388 #if defined(OS_ANDROID) | 397 #if defined(OS_ANDROID) |
389 // Android does not use native main MessageLoop. | 398 // Android does not use native main MessageLoop. |
390 NOTREACHED(); | 399 NOTREACHED(); |
391 return true; | 400 return true; |
392 #else | 401 #else |
393 base::RunLoop run_loop; | 402 base::RunLoop run_loop; |
394 base::Closure quit_closure(run_loop.QuitClosure()); | 403 base::Closure quit_closure(run_loop.QuitClosure()); |
395 RegisterClosureOnSignal(quit_closure); | 404 RegisterClosureOnSignal(&quit_closure); |
396 | 405 |
397 // If parameters_.ui_task is not NULL, we are running browser tests. | 406 // If parameters_.ui_task is not NULL, we are running browser tests. |
398 if (parameters_.ui_task) { | 407 if (parameters_.ui_task) { |
399 base::MessageLoop* message_loop = base::MessageLoopForUI::current(); | 408 base::MessageLoop* message_loop = base::MessageLoopForUI::current(); |
400 message_loop->PostTask(FROM_HERE, *parameters_.ui_task); | 409 message_loop->PostTask(FROM_HERE, *parameters_.ui_task); |
401 message_loop->PostTask(FROM_HERE, quit_closure); | 410 message_loop->PostTask(FROM_HERE, quit_closure); |
402 } | 411 } |
403 | 412 |
404 run_loop.Run(); | 413 run_loop.Run(); |
414 DeregisterClosureOnSignal(&quit_closure); | |
415 if (g_quit_signal) | |
416 LOG(INFO) << "Quitting due to signal " << g_quit_signal; | |
405 | 417 |
406 // Once the main loop has stopped running, we give the browser process a few | 418 // Once the main loop has stopped running, we give the browser process a few |
407 // seconds to stop cast service and finalize all resources. If a hang occurs | 419 // seconds to stop cast service and finalize all resources. If a hang occurs |
408 // and cast services refuse to terminate successfully, then we SIGKILL the | 420 // and cast services refuse to terminate successfully, then we SIGKILL the |
409 // current process to avoid indefinte hangs. | 421 // current process to avoid indefinte hangs. |
410 RegisterKillOnAlarm(kKillOnAlarmTimeoutSec); | 422 RegisterKillOnAlarm(kKillOnAlarmTimeoutSec); |
411 | 423 |
412 cast_browser_process_->cast_service()->Stop(); | 424 cast_browser_process_->cast_service()->Stop(); |
413 return true; | 425 return true; |
414 #endif | 426 #endif |
(...skipping 11 matching lines...) Expand all Loading... | |
426 #if defined(USE_AURA) | 438 #if defined(USE_AURA) |
427 aura::Env::DeleteInstance(); | 439 aura::Env::DeleteInstance(); |
428 #endif | 440 #endif |
429 | 441 |
430 DeregisterKillOnAlarm(); | 442 DeregisterKillOnAlarm(); |
431 #endif | 443 #endif |
432 } | 444 } |
433 | 445 |
434 } // namespace shell | 446 } // namespace shell |
435 } // namespace chromecast | 447 } // namespace chromecast |
OLD | NEW |