| 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/hi_res_timer_manager.h" | 9 #include "app/hi_res_timer_manager.h" |
| 10 #include "app/l10n_util.h" | 10 #include "app/l10n_util.h" |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 MessageLoopForUI::current()->Run(); | 164 MessageLoopForUI::current()->Run(); |
| 165 #endif | 165 #endif |
| 166 } | 166 } |
| 167 | 167 |
| 168 #if defined(OS_POSIX) | 168 #if defined(OS_POSIX) |
| 169 // See comment in BrowserMain, where sigaction is called. | 169 // See comment in BrowserMain, where sigaction is called. |
| 170 void SIGCHLDHandler(int signal) { | 170 void SIGCHLDHandler(int signal) { |
| 171 } | 171 } |
| 172 | 172 |
| 173 int g_shutdown_pipe_write_fd = -1; | 173 int g_shutdown_pipe_write_fd = -1; |
| 174 int g_shutdown_pipe_read_fd = -1; |
| 174 | 175 |
| 175 // Common code between SIG{HUP, INT, TERM}Handler. | 176 // Common code between SIG{HUP, INT, TERM}Handler. |
| 176 void GracefulShutdownHandler(int signal) { | 177 void GracefulShutdownHandler(int signal) { |
| 177 // Reinstall the default handler. We had one shot at graceful shutdown. | 178 // Reinstall the default handler. We had one shot at graceful shutdown. |
| 178 struct sigaction action; | 179 struct sigaction action; |
| 179 memset(&action, 0, sizeof(action)); | 180 memset(&action, 0, sizeof(action)); |
| 180 action.sa_handler = SIG_DFL; | 181 action.sa_handler = SIG_DFL; |
| 181 CHECK(sigaction(signal, &action, NULL) == 0); | 182 CHECK(sigaction(signal, &action, NULL) == 0); |
| 182 | 183 |
| 183 RAW_CHECK(g_shutdown_pipe_write_fd != -1); | 184 RAW_CHECK(g_shutdown_pipe_write_fd != -1); |
| 185 RAW_CHECK(g_shutdown_pipe_read_fd != -1); |
| 184 size_t bytes_written = 0; | 186 size_t bytes_written = 0; |
| 185 do { | 187 do { |
| 186 int rv = HANDLE_EINTR( | 188 int rv = HANDLE_EINTR( |
| 187 write(g_shutdown_pipe_write_fd, | 189 write(g_shutdown_pipe_write_fd, |
| 188 reinterpret_cast<const char*>(&signal) + bytes_written, | 190 reinterpret_cast<const char*>(&signal) + bytes_written, |
| 189 sizeof(signal) - bytes_written)); | 191 sizeof(signal) - bytes_written)); |
| 190 RAW_CHECK(rv >= 0); | 192 RAW_CHECK(rv >= 0); |
| 191 bytes_written += rv; | 193 bytes_written += rv; |
| 192 } while (bytes_written < sizeof(signal)); | 194 } while (bytes_written < sizeof(signal)); |
| 193 | 195 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 ssize_t ret; | 241 ssize_t ret; |
| 240 do { | 242 do { |
| 241 ret = HANDLE_EINTR( | 243 ret = HANDLE_EINTR( |
| 242 read(shutdown_fd_, | 244 read(shutdown_fd_, |
| 243 reinterpret_cast<char*>(&signal) + bytes_read, | 245 reinterpret_cast<char*>(&signal) + bytes_read, |
| 244 sizeof(signal) - bytes_read)); | 246 sizeof(signal) - bytes_read)); |
| 245 if (ret < 0) { | 247 if (ret < 0) { |
| 246 NOTREACHED() << "Unexpected error: " << strerror(errno); | 248 NOTREACHED() << "Unexpected error: " << strerror(errno); |
| 247 break; | 249 break; |
| 248 } else if (ret == 0) { | 250 } else if (ret == 0) { |
| 249 // Normal shutdown. | 251 NOTREACHED() << "Unexpected closure of shutdown pipe."; |
| 250 break; | 252 break; |
| 251 } | 253 } |
| 252 bytes_read += ret; | 254 bytes_read += ret; |
| 253 } while (bytes_read < sizeof(signal)); | 255 } while (bytes_read < sizeof(signal)); |
| 254 | 256 |
| 255 if (bytes_read == sizeof(signal)) { | 257 LOG(INFO) << "Handling shutdown for signal " << signal << "."; |
| 256 LOG(INFO) << "Handling shutdown for signal " << signal << "."; | |
| 257 | 258 |
| 258 if (!ChromeThread::PostTask( | 259 if (!ChromeThread::PostTask( |
| 259 ChromeThread::UI, FROM_HERE, | 260 ChromeThread::UI, FROM_HERE, |
| 260 NewRunnableFunction(BrowserList::CloseAllBrowsersAndExit))) { | 261 NewRunnableFunction(BrowserList::CloseAllBrowsersAndExit))) { |
| 261 // Without a UI thread to post the exit task to, there aren't many | 262 // Without a UI thread to post the exit task to, there aren't many |
| 262 // options. Raise the signal again. The default handler will pick it up | 263 // options. Raise the signal again. The default handler will pick it up |
| 263 // and cause an ungraceful exit. | 264 // and cause an ungraceful exit. |
| 264 LOG(WARNING) << "No UI thread, exiting ungracefully."; | 265 LOG(WARNING) << "No UI thread, exiting ungracefully."; |
| 265 PLOG_IF(ERROR, raise(signal) != 0) << "Failed to raise signal"; | 266 kill(getpid(), signal); |
| 266 | 267 |
| 267 // The signal may be handled on another thread. Give that a chance to | 268 // The signal may be handled on another thread. Give that a chance to |
| 268 // happen. | 269 // happen. |
| 269 sleep(3); | 270 sleep(3); |
| 270 | 271 |
| 271 // We really should be dead by now. For whatever reason, we're not. Exit | 272 // We really should be dead by now. For whatever reason, we're not. Exit |
| 272 // immediately, with the exit status set to the signal number with bit 8 | 273 // immediately, with the exit status set to the signal number with bit 8 |
| 273 // set. On the systems that we care about, this exit status is what is | 274 // set. On the systems that we care about, this exit status is what is |
| 274 // normally used to indicate an exit by this signal's default handler. | 275 // normally used to indicate an exit by this signal's default handler. |
| 275 // This mechanism isn't a de jure standard, but even in the worst case, it | 276 // This mechanism isn't a de jure standard, but even in the worst case, it |
| 276 // should at least result in an immediate exit. | 277 // should at least result in an immediate exit. |
| 277 LOG(WARNING) << "Still here, exiting really ungracefully."; | 278 LOG(WARNING) << "Still here, exiting really ungracefully."; |
| 278 _exit(signal | (1 << 7)); | 279 _exit(signal | (1 << 7)); |
| 279 } | |
| 280 } | 280 } |
| 281 | |
| 282 delete this; | |
| 283 } | 281 } |
| 284 | 282 |
| 285 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard | 283 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard |
| 286 // limit, whichever is lower. | 284 // limit, whichever is lower. |
| 287 void SetFileDescriptorLimit(unsigned int max_descriptors) { | 285 void SetFileDescriptorLimit(unsigned int max_descriptors) { |
| 288 struct rlimit limits; | 286 struct rlimit limits; |
| 289 if (getrlimit(RLIMIT_NOFILE, &limits) == 0) { | 287 if (getrlimit(RLIMIT_NOFILE, &limits) == 0) { |
| 290 unsigned int new_limit = max_descriptors; | 288 unsigned int new_limit = max_descriptors; |
| 291 if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) { | 289 if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) { |
| 292 new_limit = limits.rlim_max; | 290 new_limit = limits.rlim_max; |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 const char* thread_name = thread_name_string.c_str(); | 414 const char* thread_name = thread_name_string.c_str(); |
| 417 PlatformThread::SetName(thread_name); | 415 PlatformThread::SetName(thread_name); |
| 418 main_message_loop.set_thread_name(thread_name); | 416 main_message_loop.set_thread_name(thread_name); |
| 419 | 417 |
| 420 // Register the main thread by instantiating it, but don't call any methods. | 418 // Register the main thread by instantiating it, but don't call any methods. |
| 421 ChromeThread main_thread(ChromeThread::UI, MessageLoop::current()); | 419 ChromeThread main_thread(ChromeThread::UI, MessageLoop::current()); |
| 422 | 420 |
| 423 #if defined(OS_POSIX) | 421 #if defined(OS_POSIX) |
| 424 int pipefd[2]; | 422 int pipefd[2]; |
| 425 int ret = pipe(pipefd); | 423 int ret = pipe(pipefd); |
| 426 PlatformThreadHandle shutdown_detector_thread; | |
| 427 if (ret < 0) { | 424 if (ret < 0) { |
| 428 PLOG(DFATAL) << "Failed to create pipe"; | 425 PLOG(DFATAL) << "Failed to create pipe"; |
| 429 } else { | 426 } else { |
| 427 g_shutdown_pipe_read_fd = pipefd[0]; |
| 428 g_shutdown_pipe_write_fd = pipefd[1]; |
| 430 const size_t kShutdownDetectorThreadStackSize = 4096; | 429 const size_t kShutdownDetectorThreadStackSize = 4096; |
| 431 if (PlatformThread::Create( | 430 if (!PlatformThread::CreateNonJoinable( |
| 432 kShutdownDetectorThreadStackSize, | 431 kShutdownDetectorThreadStackSize, |
| 433 new ShutdownDetector(pipefd[0]), | 432 new ShutdownDetector(g_shutdown_pipe_read_fd))) { |
| 434 &shutdown_detector_thread)) { | |
| 435 // Successfully spawned shutdown detector thread. | |
| 436 g_shutdown_pipe_write_fd = pipefd[1]; | |
| 437 } else { | |
| 438 LOG(DFATAL) << "Failed to create shutdown detector task."; | 433 LOG(DFATAL) << "Failed to create shutdown detector task."; |
| 439 ret = HANDLE_EINTR(close(pipefd[0])); | |
| 440 PLOG_IF(ERROR, ret != 0) << "Failed to close shutdown read pipe"; | |
| 441 ret = HANDLE_EINTR(close(pipefd[1])); | |
| 442 PLOG_IF(ERROR, ret != 0) << "Failed to close shutdown write pipe"; | |
| 443 } | 434 } |
| 444 } | 435 } |
| 445 #endif // defined(OS_POSIX) | 436 #endif // defined(OS_POSIX) |
| 446 | 437 |
| 447 FilePath user_data_dir; | 438 FilePath user_data_dir; |
| 448 #if defined(OS_WIN) | 439 #if defined(OS_WIN) |
| 449 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); | 440 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); |
| 450 #else | 441 #else |
| 451 // Getting the user data dir can fail if the directory isn't | 442 // Getting the user data dir can fail if the directory isn't |
| 452 // creatable, for example; on Windows in code below we bring up a | 443 // creatable, for example; on Windows in code below we bring up a |
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 966 &result_code)) { | 957 &result_code)) { |
| 967 // Call Recycle() here as late as possible, before going into the loop | 958 // Call Recycle() here as late as possible, before going into the loop |
| 968 // because Start() will add things to it while creating the main window. | 959 // because Start() will add things to it while creating the main window. |
| 969 if (pool) | 960 if (pool) |
| 970 pool->Recycle(); | 961 pool->Recycle(); |
| 971 RunUIMessageLoop(browser_process.get()); | 962 RunUIMessageLoop(browser_process.get()); |
| 972 } | 963 } |
| 973 } | 964 } |
| 974 chrome_browser_net_websocket_experiment::WebSocketExperimentRunner::Stop(); | 965 chrome_browser_net_websocket_experiment::WebSocketExperimentRunner::Stop(); |
| 975 | 966 |
| 976 #if defined(OS_POSIX) | |
| 977 // If we initialized the shutdown pipe, then close it. | |
| 978 if (g_shutdown_pipe_write_fd != -1) { | |
| 979 ret = HANDLE_EINTR(close(g_shutdown_pipe_write_fd)); | |
| 980 g_shutdown_pipe_write_fd = -1; | |
| 981 PLOG_IF(ERROR, ret != 0) << "Failed to close"; | |
| 982 } | |
| 983 #endif // defined(OS_POSIX) | |
| 984 | |
| 985 process_singleton.Cleanup(); | 967 process_singleton.Cleanup(); |
| 986 | 968 |
| 987 Platform::DidEndMainMessageLoop(); | 969 Platform::DidEndMainMessageLoop(); |
| 988 | 970 |
| 989 if (metrics) | 971 if (metrics) |
| 990 metrics->Stop(); | 972 metrics->Stop(); |
| 991 | 973 |
| 992 // browser_shutdown takes care of deleting browser_process, so we need to | 974 // browser_shutdown takes care of deleting browser_process, so we need to |
| 993 // release it. | 975 // release it. |
| 994 browser_process.release(); | 976 browser_process.release(); |
| 995 browser_shutdown::Shutdown(); | 977 browser_shutdown::Shutdown(); |
| 996 | 978 |
| 997 return result_code; | 979 return result_code; |
| 998 } | 980 } |
| OLD | NEW |