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 513e6f8078a595f87aff90060368b8ee4c319fac..e3278c122fb4005028fbe2164d5f368718cb1b42 100644 |
| --- a/chromecast/browser/cast_browser_main_parts.cc |
| +++ b/chromecast/browser/cast_browser_main_parts.cc |
| @@ -4,8 +4,10 @@ |
| #include "chromecast/browser/cast_browser_main_parts.h" |
| +#if !defined(OS_ANDROID) |
| #include <signal.h> |
| #include <sys/prctl.h> |
| +#endif |
| #include "base/command_line.h" |
| #include "base/files/file_util.h" |
| @@ -81,6 +83,49 @@ void RegisterClosureOnSignal(const base::Closure& closure) { |
| // Get the first signal to exit when the parent process dies. |
| prctl(PR_SET_PDEATHSIG, kSignalsToRunClosure[0]); |
| } |
| + |
| +const int kKillOnAlarmTimeoutSec = 5; // 5 seconds |
| + |
| +void KillOnAlarm(int signum) { |
| + LOG(ERROR) << "Got alarm signal for termination: " << signum; |
| + raise(SIGKILL); |
| +} |
| + |
| +void RegisterKillOnAlarm(int timeout_seconds) { |
| + struct sigaction sa_new; |
| + memset(&sa_new, 0, sizeof(sa_new)); |
| + sa_new.sa_handler = KillOnAlarm; |
| + sigfillset(&sa_new.sa_mask); |
| + sa_new.sa_flags = SA_RESTART; |
| + |
| + struct sigaction sa_old; |
| + if (sigaction(SIGALRM, &sa_new, &sa_old) == -1) { |
| + NOTREACHED(); |
| + } else { |
| + DCHECK_EQ(sa_old.sa_handler, SIG_DFL); |
| + } |
| + |
| + if (alarm(timeout_seconds) > 0) |
| + NOTREACHED() << "Previous alarm() was cancelled"; |
| +} |
| + |
| +void DeregisterKillOnAlarm() { |
| + // Explicitly cancel any outstanding alarm() calls. |
| + alarm(0); |
| + |
| + struct sigaction sa_new; |
| + memset(&sa_new, 0, sizeof(sa_new)); |
| + sa_new.sa_handler = SIG_DFL; |
| + sigfillset(&sa_new.sa_mask); |
| + sa_new.sa_flags = SA_RESTART; |
| + |
| + struct sigaction sa_old; |
| + if (sigaction(SIGALRM, &sa_new, &sa_old) == -1) { |
| + NOTREACHED(); |
| + } else { |
| + DCHECK_EQ(sa_old.sa_handler, KillOnAlarm); |
| + } |
| +} |
| #endif // !defined(OS_ANDROID) |
| } // namespace |
| @@ -267,6 +312,12 @@ bool CastBrowserMainParts::MainMessageLoopRun(int* result_code) { |
| run_loop.Run(); |
| + // 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 |
| + // and cast services refuse to terminate successfully, then we SIGKILL the |
| + // current process to avoid indefinte hangs. |
| + RegisterKillOnAlarm(kKillOnAlarmTimeoutSec); |
| + |
| cast_browser_process_->cast_service()->Stop(); |
| return true; |
| #endif |
| @@ -280,6 +331,7 @@ void CastBrowserMainParts::PostMainMessageLoopRun() { |
| cast_browser_process_->cast_service()->Finalize(); |
| cast_browser_process_->metrics_service_client()->Finalize(); |
| cast_browser_process_.reset(); |
| + DeregisterKillOnAlarm(); |
|
byungchul
2015/03/23 20:51:11
Not sure if it is useful.
maclellant
2015/03/23 21:12:45
It seems cleaner to me to remove any side effects
|
| #endif |
| } |