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