| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_posix.h" | 5 #include "chrome/browser/browser_main_posix.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <limits.h> |
| 8 #include <signal.h> | 9 #include <signal.h> |
| 9 #include <sys/resource.h> | 10 #include <sys/resource.h> |
| 11 #include <unistd.h> |
| 10 | 12 |
| 11 #include <string> | 13 #include <string> |
| 12 | 14 |
| 13 #include "base/command_line.h" | 15 #include "base/command_line.h" |
| 14 #include "base/eintr_wrapper.h" | 16 #include "base/eintr_wrapper.h" |
| 15 #include "base/logging.h" | 17 #include "base/logging.h" |
| 16 #include "base/string_number_conversions.h" | 18 #include "base/string_number_conversions.h" |
| 17 #include "base/threading/platform_thread.h" | |
| 18 #include "chrome/browser/defaults.h" | 19 #include "chrome/browser/defaults.h" |
| 19 #include "chrome/browser/ui/browser_list.h" | 20 #include "chrome/browser/ui/browser_list.h" |
| 20 #include "chrome/common/chrome_switches.h" | 21 #include "chrome/common/chrome_switches.h" |
| 21 #include "content/browser/browser_thread.h" | 22 #include "content/browser/browser_thread.h" |
| 22 | 23 |
| 23 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 24 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 24 #include "chrome/browser/printing/print_dialog_gtk.h" | 25 #include "chrome/browser/printing/print_dialog_gtk.h" |
| 25 #endif | 26 #endif |
| 26 | 27 |
| 27 namespace { | 28 namespace { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 const int shutdown_fd_; | 83 const int shutdown_fd_; |
| 83 | 84 |
| 84 DISALLOW_COPY_AND_ASSIGN(ShutdownDetector); | 85 DISALLOW_COPY_AND_ASSIGN(ShutdownDetector); |
| 85 }; | 86 }; |
| 86 | 87 |
| 87 ShutdownDetector::ShutdownDetector(int shutdown_fd) | 88 ShutdownDetector::ShutdownDetector(int shutdown_fd) |
| 88 : shutdown_fd_(shutdown_fd) { | 89 : shutdown_fd_(shutdown_fd) { |
| 89 CHECK_NE(shutdown_fd_, -1); | 90 CHECK_NE(shutdown_fd_, -1); |
| 90 } | 91 } |
| 91 | 92 |
| 93 |
| 94 // These functions are used to help us diagnose crash dumps that happen |
| 95 // during the shutdown process. |
| 96 NOINLINE void ShutdownFDReadError() { |
| 97 // Ensure function isn't optimized away. |
| 98 asm(""); |
| 99 sleep(UINT_MAX); |
| 100 } |
| 101 |
| 102 NOINLINE void ShutdownFDClosedError() { |
| 103 // Ensure function isn't optimized away. |
| 104 asm(""); |
| 105 sleep(UINT_MAX); |
| 106 } |
| 107 |
| 108 NOINLINE void CloseAllBrowsersAndExitPosted() { |
| 109 // Ensure function isn't optimized away. |
| 110 asm(""); |
| 111 sleep(UINT_MAX); |
| 112 } |
| 113 |
| 92 void ShutdownDetector::ThreadMain() { | 114 void ShutdownDetector::ThreadMain() { |
| 93 base::PlatformThread::SetName("CrShutdownDetector"); | 115 base::PlatformThread::SetName("CrShutdownDetector"); |
| 94 | 116 |
| 95 int signal; | 117 int signal; |
| 96 size_t bytes_read = 0; | 118 size_t bytes_read = 0; |
| 97 ssize_t ret; | 119 ssize_t ret; |
| 98 do { | 120 do { |
| 99 ret = HANDLE_EINTR( | 121 ret = HANDLE_EINTR( |
| 100 read(shutdown_fd_, | 122 read(shutdown_fd_, |
| 101 reinterpret_cast<char*>(&signal) + bytes_read, | 123 reinterpret_cast<char*>(&signal) + bytes_read, |
| 102 sizeof(signal) - bytes_read)); | 124 sizeof(signal) - bytes_read)); |
| 103 if (ret < 0) { | 125 if (ret < 0) { |
| 104 NOTREACHED() << "Unexpected error: " << strerror(errno); | 126 NOTREACHED() << "Unexpected error: " << strerror(errno); |
| 127 ShutdownFDReadError(); |
| 105 break; | 128 break; |
| 106 } else if (ret == 0) { | 129 } else if (ret == 0) { |
| 107 NOTREACHED() << "Unexpected closure of shutdown pipe."; | 130 NOTREACHED() << "Unexpected closure of shutdown pipe."; |
| 131 ShutdownFDClosedError(); |
| 108 break; | 132 break; |
| 109 } | 133 } |
| 110 bytes_read += ret; | 134 bytes_read += ret; |
| 111 } while (bytes_read < sizeof(signal)); | 135 } while (bytes_read < sizeof(signal)); |
| 112 | 136 |
| 113 VLOG(1) << "Handling shutdown for signal " << signal << "."; | 137 VLOG(1) << "Handling shutdown for signal " << signal << "."; |
| 114 | 138 |
| 115 if (!BrowserThread::PostTask( | 139 if (!BrowserThread::PostTask( |
| 116 BrowserThread::UI, FROM_HERE, | 140 BrowserThread::UI, FROM_HERE, |
| 117 NewRunnableFunction(BrowserList::CloseAllBrowsersAndExit))) { | 141 NewRunnableFunction(BrowserList::CloseAllBrowsersAndExit))) { |
| 118 // Without a UI thread to post the exit task to, there aren't many | 142 // Without a UI thread to post the exit task to, there aren't many |
| 119 // options. Raise the signal again. The default handler will pick it up | 143 // options. Raise the signal again. The default handler will pick it up |
| 120 // and cause an ungraceful exit. | 144 // and cause an ungraceful exit. |
| 121 RAW_LOG(WARNING, "No UI thread, exiting ungracefully."); | 145 RAW_LOG(WARNING, "No UI thread, exiting ungracefully."); |
| 122 kill(getpid(), signal); | 146 kill(getpid(), signal); |
| 123 | 147 |
| 124 // The signal may be handled on another thread. Give that a chance to | 148 // The signal may be handled on another thread. Give that a chance to |
| 125 // happen. | 149 // happen. |
| 126 sleep(3); | 150 sleep(3); |
| 127 | 151 |
| 128 // We really should be dead by now. For whatever reason, we're not. Exit | 152 // We really should be dead by now. For whatever reason, we're not. Exit |
| 129 // immediately, with the exit status set to the signal number with bit 8 | 153 // immediately, with the exit status set to the signal number with bit 8 |
| 130 // set. On the systems that we care about, this exit status is what is | 154 // set. On the systems that we care about, this exit status is what is |
| 131 // normally used to indicate an exit by this signal's default handler. | 155 // normally used to indicate an exit by this signal's default handler. |
| 132 // This mechanism isn't a de jure standard, but even in the worst case, it | 156 // This mechanism isn't a de jure standard, but even in the worst case, it |
| 133 // should at least result in an immediate exit. | 157 // should at least result in an immediate exit. |
| 134 RAW_LOG(WARNING, "Still here, exiting really ungracefully."); | 158 RAW_LOG(WARNING, "Still here, exiting really ungracefully."); |
| 135 _exit(signal | (1 << 7)); | 159 _exit(signal | (1 << 7)); |
| 136 } | 160 } |
| 161 CloseAllBrowsersAndExitPosted(); |
| 137 } | 162 } |
| 138 | 163 |
| 139 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard | 164 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard |
| 140 // limit, whichever is lower. | 165 // limit, whichever is lower. |
| 141 void SetFileDescriptorLimit(unsigned int max_descriptors) { | 166 void SetFileDescriptorLimit(unsigned int max_descriptors) { |
| 142 struct rlimit limits; | 167 struct rlimit limits; |
| 143 if (getrlimit(RLIMIT_NOFILE, &limits) == 0) { | 168 if (getrlimit(RLIMIT_NOFILE, &limits) == 0) { |
| 144 unsigned int new_limit = max_descriptors; | 169 unsigned int new_limit = max_descriptors; |
| 145 if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) { | 170 if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) { |
| 146 new_limit = limits.rlim_max; | 171 new_limit = limits.rlim_max; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 new ShutdownDetector(g_shutdown_pipe_read_fd))) { | 253 new ShutdownDetector(g_shutdown_pipe_read_fd))) { |
| 229 LOG(DFATAL) << "Failed to create shutdown detector task."; | 254 LOG(DFATAL) << "Failed to create shutdown detector task."; |
| 230 } | 255 } |
| 231 } | 256 } |
| 232 | 257 |
| 233 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 258 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 234 printing::PrintingContextCairo::SetCreatePrintDialogFunction( | 259 printing::PrintingContextCairo::SetCreatePrintDialogFunction( |
| 235 &PrintDialogGtk::CreatePrintDialog); | 260 &PrintDialogGtk::CreatePrintDialog); |
| 236 #endif // defined(OS_LINUX) && !defined(OS_CHROMEOS) | 261 #endif // defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 237 } | 262 } |
| OLD | NEW |