Chromium Code Reviews| 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 <signal.h> | 8 #include <signal.h> |
| 9 #include <sys/resource.h> | 9 #include <sys/resource.h> |
| 10 | 10 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 82 const int shutdown_fd_; | 82 const int shutdown_fd_; |
| 83 | 83 |
| 84 DISALLOW_COPY_AND_ASSIGN(ShutdownDetector); | 84 DISALLOW_COPY_AND_ASSIGN(ShutdownDetector); |
| 85 }; | 85 }; |
| 86 | 86 |
| 87 ShutdownDetector::ShutdownDetector(int shutdown_fd) | 87 ShutdownDetector::ShutdownDetector(int shutdown_fd) |
| 88 : shutdown_fd_(shutdown_fd) { | 88 : shutdown_fd_(shutdown_fd) { |
| 89 CHECK_NE(shutdown_fd_, -1); | 89 CHECK_NE(shutdown_fd_, -1); |
| 90 } | 90 } |
| 91 | 91 |
| 92 | |
| 93 // These functions are used to help us diagnose crash dumps that happen | |
| 94 // during the shutdown process. | |
| 95 #define NOINLINE __attribute__((noinline)) | |
| 96 | |
| 97 NOINLINE void ShutdownFDReadError() { | |
| 98 sleep(UINT_MAX); | |
|
willchan no longer on Chromium
2011/05/04 21:06:49
I think you need <limits.h> for this constant and
DaveMoore
2011/05/09 17:41:42
Done. I kept the sleep() call, added the asm("") a
| |
| 99 } | |
| 100 | |
| 101 NOINLINE void ShutdownFDClosedError() { | |
| 102 sleep(UINT_MAX); | |
| 103 } | |
| 104 | |
| 105 NOINLINE void CloseAllBrowsersAndExitPosted() { | |
| 106 sleep(UINT_MAX); | |
| 107 } | |
| 108 | |
| 92 void ShutdownDetector::ThreadMain() { | 109 void ShutdownDetector::ThreadMain() { |
| 93 base::PlatformThread::SetName("CrShutdownDetector"); | 110 base::PlatformThread::SetName("CrShutdownDetector"); |
| 94 | 111 |
| 95 int signal; | 112 int signal; |
| 96 size_t bytes_read = 0; | 113 size_t bytes_read = 0; |
| 97 ssize_t ret; | 114 ssize_t ret; |
| 98 do { | 115 do { |
| 99 ret = HANDLE_EINTR( | 116 ret = HANDLE_EINTR( |
| 100 read(shutdown_fd_, | 117 read(shutdown_fd_, |
| 101 reinterpret_cast<char*>(&signal) + bytes_read, | 118 reinterpret_cast<char*>(&signal) + bytes_read, |
| 102 sizeof(signal) - bytes_read)); | 119 sizeof(signal) - bytes_read)); |
| 103 if (ret < 0) { | 120 if (ret < 0) { |
| 104 NOTREACHED() << "Unexpected error: " << strerror(errno); | 121 NOTREACHED() << "Unexpected error: " << strerror(errno); |
| 122 ShutdownFDReadError(); | |
| 105 break; | 123 break; |
| 106 } else if (ret == 0) { | 124 } else if (ret == 0) { |
| 107 NOTREACHED() << "Unexpected closure of shutdown pipe."; | 125 NOTREACHED() << "Unexpected closure of shutdown pipe."; |
| 126 ShutdownFDClosedError(); | |
| 108 break; | 127 break; |
| 109 } | 128 } |
| 110 bytes_read += ret; | 129 bytes_read += ret; |
| 111 } while (bytes_read < sizeof(signal)); | 130 } while (bytes_read < sizeof(signal)); |
| 112 | 131 |
| 113 VLOG(1) << "Handling shutdown for signal " << signal << "."; | 132 VLOG(1) << "Handling shutdown for signal " << signal << "."; |
| 114 | 133 |
| 115 if (!BrowserThread::PostTask( | 134 if (!BrowserThread::PostTask( |
| 116 BrowserThread::UI, FROM_HERE, | 135 BrowserThread::UI, FROM_HERE, |
| 117 NewRunnableFunction(BrowserList::CloseAllBrowsersAndExit))) { | 136 NewRunnableFunction(BrowserList::CloseAllBrowsersAndExit))) { |
| 118 // Without a UI thread to post the exit task to, there aren't many | 137 // 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 | 138 // options. Raise the signal again. The default handler will pick it up |
| 120 // and cause an ungraceful exit. | 139 // and cause an ungraceful exit. |
| 121 RAW_LOG(WARNING, "No UI thread, exiting ungracefully."); | 140 RAW_LOG(WARNING, "No UI thread, exiting ungracefully."); |
| 122 kill(getpid(), signal); | 141 kill(getpid(), signal); |
| 123 | 142 |
| 124 // The signal may be handled on another thread. Give that a chance to | 143 // The signal may be handled on another thread. Give that a chance to |
| 125 // happen. | 144 // happen. |
| 126 sleep(3); | 145 sleep(3); |
| 127 | 146 |
| 128 // We really should be dead by now. For whatever reason, we're not. Exit | 147 // 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 | 148 // 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 | 149 // 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. | 150 // 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 | 151 // This mechanism isn't a de jure standard, but even in the worst case, it |
| 133 // should at least result in an immediate exit. | 152 // should at least result in an immediate exit. |
| 134 RAW_LOG(WARNING, "Still here, exiting really ungracefully."); | 153 RAW_LOG(WARNING, "Still here, exiting really ungracefully."); |
| 135 _exit(signal | (1 << 7)); | 154 _exit(signal | (1 << 7)); |
| 136 } | 155 } |
| 156 CloseAllBrowsersAndExitPosted(); | |
| 137 } | 157 } |
| 138 | 158 |
| 139 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard | 159 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard |
| 140 // limit, whichever is lower. | 160 // limit, whichever is lower. |
| 141 void SetFileDescriptorLimit(unsigned int max_descriptors) { | 161 void SetFileDescriptorLimit(unsigned int max_descriptors) { |
| 142 struct rlimit limits; | 162 struct rlimit limits; |
| 143 if (getrlimit(RLIMIT_NOFILE, &limits) == 0) { | 163 if (getrlimit(RLIMIT_NOFILE, &limits) == 0) { |
| 144 unsigned int new_limit = max_descriptors; | 164 unsigned int new_limit = max_descriptors; |
| 145 if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) { | 165 if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) { |
| 146 new_limit = limits.rlim_max; | 166 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))) { | 248 new ShutdownDetector(g_shutdown_pipe_read_fd))) { |
| 229 LOG(DFATAL) << "Failed to create shutdown detector task."; | 249 LOG(DFATAL) << "Failed to create shutdown detector task."; |
| 230 } | 250 } |
| 231 } | 251 } |
| 232 | 252 |
| 233 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 253 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 234 printing::PrintingContextCairo::SetCreatePrintDialogFunction( | 254 printing::PrintingContextCairo::SetCreatePrintDialogFunction( |
| 235 &PrintDialogGtk::CreatePrintDialog); | 255 &PrintDialogGtk::CreatePrintDialog); |
| 236 #endif // defined(OS_LINUX) && !defined(OS_CHROMEOS) | 256 #endif // defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 237 } | 257 } |
| OLD | NEW |