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..b907ad9a395a515cc3902dd51773b951c3504444 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,47 @@ 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"; |
+ } |
byungchul
2015/03/23 20:00:35
remove {}
maclellant
2015/03/23 20:24:28
Done.
|
+} |
+ |
+void DeregisterKillOnAlarm() { |
+ 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 |
@@ -277,9 +320,14 @@ void CastBrowserMainParts::PostMainMessageLoopRun() { |
// Android does not use native main MessageLoop. |
NOTREACHED(); |
#else |
+ // If the services owned by the browser process do not finalize correctly, we |
+ // trigger a SIGKILL on the current process to forcibly terminate. This avoids |
+ // indefinte hangs when resources cannot clean up properly. |
+ RegisterKillOnAlarm(kKillOnAlarmTimeoutSec); |
byungchul
2015/03/23 20:00:35
Should it be before cast_browser_process_->cast_se
gunsch
2015/03/23 20:14:21
+1
maclellant
2015/03/23 20:24:28
Done.
|
cast_browser_process_->cast_service()->Finalize(); |
cast_browser_process_->metrics_service_client()->Finalize(); |
cast_browser_process_.reset(); |
+ DeregisterKillOnAlarm(); |
#endif |
} |