| OLD | NEW |
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 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 "chrome/browser/browser_main.h" | 5 #include "chrome/browser/browser_main.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "app/l10n_util.h" | 9 #include "app/l10n_util.h" |
| 10 #include "app/resource_bundle.h" | 10 #include "app/resource_bundle.h" |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 #elif defined(OS_POSIX) | 160 #elif defined(OS_POSIX) |
| 161 MessageLoopForUI::current()->Run(); | 161 MessageLoopForUI::current()->Run(); |
| 162 #endif | 162 #endif |
| 163 } | 163 } |
| 164 | 164 |
| 165 #if defined(OS_POSIX) | 165 #if defined(OS_POSIX) |
| 166 // See comment in BrowserMain, where sigaction is called. | 166 // See comment in BrowserMain, where sigaction is called. |
| 167 void SIGCHLDHandler(int signal) { | 167 void SIGCHLDHandler(int signal) { |
| 168 } | 168 } |
| 169 | 169 |
| 170 // See comment in BrowserMain, where sigaction is called. | 170 // Common code between SIG{HUP, INT, TERM}Handler. |
| 171 void SIGTERMHandler(int signal) { | 171 void GracefulShutdownHandler(int signal, const int expected_signal) { |
| 172 DCHECK_EQ(signal, SIGTERM); | 172 DCHECK_EQ(signal, expected_signal); |
| 173 LOG(WARNING) << "Addressing SIGTERM on " << PlatformThread::CurrentId(); | 173 LOG(WARNING) << "Addressing signal " << expected_signal << " on " |
| 174 << PlatformThread::CurrentId(); |
| 174 | 175 |
| 175 bool posted = ChromeThread::PostTask( | 176 bool posted = ChromeThread::PostTask( |
| 176 ChromeThread::UI, FROM_HERE, | 177 ChromeThread::UI, FROM_HERE, |
| 177 NewRunnableFunction(BrowserList::CloseAllBrowsersAndExit)); | 178 NewRunnableFunction(BrowserList::CloseAllBrowsersAndExit)); |
| 178 if (posted) { | |
| 179 LOG(WARNING) << "Posted task to UI thread; resetting SIGTERM handler"; | |
| 180 } | |
| 181 | 179 |
| 182 // Reinstall the default handler. We had one shot at graceful shutdown. | 180 // Reinstall the default handler. We had one shot at graceful shutdown. |
| 183 struct sigaction term_action; | 181 struct sigaction term_action; |
| 184 memset(&term_action, 0, sizeof(term_action)); | 182 memset(&term_action, 0, sizeof(term_action)); |
| 185 term_action.sa_handler = SIG_DFL; | 183 term_action.sa_handler = SIG_DFL; |
| 186 CHECK(sigaction(SIGTERM, &term_action, NULL) == 0); | 184 CHECK(sigaction(expected_signal, &term_action, NULL) == 0); |
| 187 | 185 |
| 188 if (!posted) { | 186 if (posted) { |
| 187 LOG(WARNING) << "Posted task to UI thread; resetting signal " |
| 188 << expected_signal << " handler"; |
| 189 } else { |
| 189 // Without a UI thread to post the exit task to, there aren't many | 190 // Without a UI thread to post the exit task to, there aren't many |
| 190 // options. Raise the signal again. The default handler will pick it up | 191 // options. Raise the signal again. The default handler will pick it up |
| 191 // and cause an ungraceful exit. | 192 // and cause an ungraceful exit. |
| 192 LOG(WARNING) << "No UI thread, exiting ungracefully"; | 193 LOG(WARNING) << "No UI thread, exiting ungracefully"; |
| 193 kill(getpid(), signal); | 194 kill(getpid(), signal); |
| 194 | 195 |
| 195 // The signal may be handled on another thread. Give that a chance to | 196 // The signal may be handled on another thread. Give that a chance to |
| 196 // happen. | 197 // happen. |
| 197 sleep(3); | 198 sleep(3); |
| 198 | 199 |
| 199 // We really should be dead by now. For whatever reason, we're not. Exit | 200 // We really should be dead by now. For whatever reason, we're not. Exit |
| 200 // immediately, with the exit status set to the signal number with bit 8 | 201 // immediately, with the exit status set to the signal number with bit 8 |
| 201 // set. On the systems that we care about, this exit status is what is | 202 // set. On the systems that we care about, this exit status is what is |
| 202 // normally used to indicate an exit by this signal's default handler. | 203 // normally used to indicate an exit by this signal's default handler. |
| 203 // This mechanism isn't a de jure standard, but even in the worst case, it | 204 // This mechanism isn't a de jure standard, but even in the worst case, it |
| 204 // should at least result in an immediate exit. | 205 // should at least result in an immediate exit. |
| 205 LOG(WARNING) << "Still here, exiting really ungracefully"; | 206 LOG(WARNING) << "Still here, exiting really ungracefully"; |
| 206 _exit(signal | (1 << 7)); | 207 _exit(signal | (1 << 7)); |
| 207 } | 208 } |
| 208 } | 209 } |
| 209 | 210 |
| 211 // See comment in BrowserMain, where sigaction is called. |
| 212 void SIGHUPHandler(int signal) { |
| 213 GracefulShutdownHandler(signal, SIGHUP); |
| 214 } |
| 215 |
| 216 // See comment in BrowserMain, where sigaction is called. |
| 217 void SIGINTHandler(int signal) { |
| 218 GracefulShutdownHandler(signal, SIGINT); |
| 219 } |
| 220 |
| 221 // See comment in BrowserMain, where sigaction is called. |
| 222 void SIGTERMHandler(int signal) { |
| 223 GracefulShutdownHandler(signal, SIGTERM); |
| 224 } |
| 225 |
| 210 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard | 226 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard |
| 211 // limit, whichever is lower. | 227 // limit, whichever is lower. |
| 212 void SetFileDescriptorLimit(unsigned int max_descriptors) { | 228 void SetFileDescriptorLimit(unsigned int max_descriptors) { |
| 213 struct rlimit limits; | 229 struct rlimit limits; |
| 214 if (getrlimit(RLIMIT_NOFILE, &limits) == 0) { | 230 if (getrlimit(RLIMIT_NOFILE, &limits) == 0) { |
| 215 unsigned int new_limit = max_descriptors; | 231 unsigned int new_limit = max_descriptors; |
| 216 if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) { | 232 if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) { |
| 217 new_limit = limits.rlim_max; | 233 new_limit = limits.rlim_max; |
| 218 } | 234 } |
| 219 limits.rlim_cur = new_limit; | 235 limits.rlim_cur = new_limit; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 memset(&action, 0, sizeof(action)); | 300 memset(&action, 0, sizeof(action)); |
| 285 action.sa_handler = SIGCHLDHandler; | 301 action.sa_handler = SIGCHLDHandler; |
| 286 CHECK(sigaction(SIGCHLD, &action, NULL) == 0); | 302 CHECK(sigaction(SIGCHLD, &action, NULL) == 0); |
| 287 | 303 |
| 288 // We need to handle SIGTERM, because that is how many POSIX-based distros ask | 304 // We need to handle SIGTERM, because that is how many POSIX-based distros ask |
| 289 // processes to quit gracefully at shutdown time. | 305 // processes to quit gracefully at shutdown time. |
| 290 struct sigaction term_action; | 306 struct sigaction term_action; |
| 291 memset(&term_action, 0, sizeof(term_action)); | 307 memset(&term_action, 0, sizeof(term_action)); |
| 292 term_action.sa_handler = SIGTERMHandler; | 308 term_action.sa_handler = SIGTERMHandler; |
| 293 CHECK(sigaction(SIGTERM, &term_action, NULL) == 0); | 309 CHECK(sigaction(SIGTERM, &term_action, NULL) == 0); |
| 310 // Also handle SIGINT - when the user terminates the browser via Ctrl+C. |
| 311 // If the browser process is being debugged, GDB will catch the SIGINT first. |
| 312 CHECK(sigaction(SIGINT, &term_action, NULL) == 0); |
| 313 // And SIGHUP, for when the terminal disappears. On shutdown, many Linux |
| 314 // distros send SIGHUP, SIGTERM, and then SIGKILL. |
| 315 CHECK(sigaction(SIGHUP, &term_action, NULL) == 0); |
| 294 | 316 |
| 295 const std::wstring fd_limit_string = | 317 const std::wstring fd_limit_string = |
| 296 parsed_command_line.GetSwitchValue(switches::kFileDescriptorLimit); | 318 parsed_command_line.GetSwitchValue(switches::kFileDescriptorLimit); |
| 297 int fd_limit = 0; | 319 int fd_limit = 0; |
| 298 if (!fd_limit_string.empty()) { | 320 if (!fd_limit_string.empty()) { |
| 299 StringToInt(WideToUTF16Hack(fd_limit_string), &fd_limit); | 321 StringToInt(WideToUTF16Hack(fd_limit_string), &fd_limit); |
| 300 } | 322 } |
| 301 #if defined(OS_MACOSX) | 323 #if defined(OS_MACOSX) |
| 302 // We use quite a few file descriptors for our IPC, and the default limit on | 324 // We use quite a few file descriptors for our IPC, and the default limit on |
| 303 // the Mac is low (256), so bump it up if there is no explicit override. | 325 // the Mac is low (256), so bump it up if there is no explicit override. |
| (...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 if (metrics) | 923 if (metrics) |
| 902 metrics->Stop(); | 924 metrics->Stop(); |
| 903 | 925 |
| 904 // browser_shutdown takes care of deleting browser_process, so we need to | 926 // browser_shutdown takes care of deleting browser_process, so we need to |
| 905 // release it. | 927 // release it. |
| 906 browser_process.release(); | 928 browser_process.release(); |
| 907 browser_shutdown::Shutdown(); | 929 browser_shutdown::Shutdown(); |
| 908 | 930 |
| 909 return result_code; | 931 return result_code; |
| 910 } | 932 } |
| OLD | NEW |