Chromium Code Reviews| Index: chromecast/browser/cast_browser_main_parts.cc |
| diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc |
| index 14f23316fdbcb325950edcc800116b23e304fcae..2c5a8aae18204da1db6d92b016f2e311b9ca7ffc 100644 |
| --- a/chromecast/browser/cast_browser_main_parts.cc |
| +++ b/chromecast/browser/cast_browser_main_parts.cc |
| @@ -76,24 +76,27 @@ namespace { |
| #if !defined(OS_ANDROID) |
| int kSignalsToRunClosure[] = { SIGTERM, SIGINT, }; |
| - |
| // Closure to run on SIGTERM and SIGINT. |
| base::Closure* g_signal_closure = NULL; |
| +base::PlatformThreadId g_main_thread_id; |
| +int g_quit_signal = 0; |
| void RunClosureOnSignal(int signum) { |
| - LOG(ERROR) << "Got signal " << signum; |
|
maclellant
2015/12/28 19:30:32
This printing is still useful to detect the cases
kmackay
2015/12/29 18:23:01
Done.
|
| - DCHECK(g_signal_closure); |
| - // Expect main thread got this signal. Otherwise, weak_ptr of run_loop will |
| - // crash the process. |
| + if (base::PlatformThread::CurrentId() != g_main_thread_id) |
| + return; |
| + if (!g_signal_closure) |
| + return; |
| + g_quit_signal = signum; |
| g_signal_closure->Run(); |
| } |
| -void RegisterClosureOnSignal(const base::Closure& closure) { |
| +void RegisterClosureOnSignal(base::Closure* closure) { |
| + DCHECK(closure); |
| DCHECK(!g_signal_closure); |
| DCHECK_GT(arraysize(kSignalsToRunClosure), 0U); |
| - // Allow memory leak by intention. |
| - g_signal_closure = new base::Closure(closure); |
| + g_signal_closure = closure; |
| + g_main_thread_id = base::PlatformThread::CurrentId(); |
| struct sigaction sa_new; |
| memset(&sa_new, 0, sizeof(sa_new)); |
| @@ -101,9 +104,9 @@ void RegisterClosureOnSignal(const base::Closure& closure) { |
| sigfillset(&sa_new.sa_mask); |
| sa_new.sa_flags = SA_RESTART; |
| - for (size_t i = 0; i < arraysize(kSignalsToRunClosure); i++) { |
| + for (int sig : kSignalsToRunClosure) { |
| struct sigaction sa_old; |
| - if (sigaction(kSignalsToRunClosure[i], &sa_new, &sa_old) == -1) { |
| + if (sigaction(sig, &sa_new, &sa_old) == -1) { |
| NOTREACHED(); |
| } else { |
| 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
|
| @@ -114,6 +117,12 @@ void RegisterClosureOnSignal(const base::Closure& closure) { |
| prctl(PR_SET_PDEATHSIG, kSignalsToRunClosure[0]); |
| } |
| +void DeregisterClosureOnSignal(base::Closure* closure) { |
| + DCHECK_EQ(g_signal_closure, closure); |
| + DCHECK_EQ(g_main_thread_id, base::PlatformThread::CurrentId()); |
| + 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
|
| +} |
| + |
| const int kKillOnAlarmTimeoutSec = 5; // 5 seconds |
| void KillOnAlarm(int signum) { |
| @@ -392,7 +401,7 @@ bool CastBrowserMainParts::MainMessageLoopRun(int* result_code) { |
| #else |
| base::RunLoop run_loop; |
| base::Closure quit_closure(run_loop.QuitClosure()); |
| - RegisterClosureOnSignal(quit_closure); |
| + RegisterClosureOnSignal(&quit_closure); |
| // If parameters_.ui_task is not NULL, we are running browser tests. |
| if (parameters_.ui_task) { |
| @@ -402,6 +411,9 @@ bool CastBrowserMainParts::MainMessageLoopRun(int* result_code) { |
| } |
| run_loop.Run(); |
| + DeregisterClosureOnSignal(&quit_closure); |
| + if (g_quit_signal) |
| + LOG(INFO) << "Quitting due to signal " << g_quit_signal; |
| // Once the main loop has stopped running, we give the browser process a few |
| // seconds to stop cast service and finalize all resources. If a hang occurs |