Chromium Code Reviews| 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 |