Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Unified Diff: chromecast/browser/cast_browser_main_parts.cc

Issue 1002603006: Raise SIGKILL if cast_service doesn't Finalize() within timeout. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cancel outstanding alarm calls when deregistering handler. Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698