| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "app/hi_res_timer_manager.h" | 5 #include "app/hi_res_timer_manager.h" |
| 6 #include "app/l10n_util.h" | 6 #include "app/l10n_util.h" |
| 7 #include "app/resource_bundle.h" | 7 #include "app/resource_bundle.h" |
| 8 #include "app/system_monitor.h" | 8 #include "app/system_monitor.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/field_trial.h" | 10 #include "base/field_trial.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #include "chrome/common/chrome_switches.h" | 21 #include "chrome/common/chrome_switches.h" |
| 22 #include "chrome/common/logging_chrome.h" | 22 #include "chrome/common/logging_chrome.h" |
| 23 #include "chrome/common/main_function_params.h" | 23 #include "chrome/common/main_function_params.h" |
| 24 #include "chrome/common/net/net_resource_provider.h" | 24 #include "chrome/common/net/net_resource_provider.h" |
| 25 #include "chrome/renderer/renderer_main_platform_delegate.h" | 25 #include "chrome/renderer/renderer_main_platform_delegate.h" |
| 26 #include "chrome/renderer/render_process.h" | 26 #include "chrome/renderer/render_process.h" |
| 27 #include "chrome/renderer/render_thread.h" | 27 #include "chrome/renderer/render_thread.h" |
| 28 #include "grit/generated_resources.h" | 28 #include "grit/generated_resources.h" |
| 29 #include "net/base/net_module.h" | 29 #include "net/base/net_module.h" |
| 30 | 30 |
| 31 #if defined(OS_MACOSX) |
| 32 #include "base/eintr_wrapper.h" |
| 33 #include "chrome/app/breakpad_mac.h" |
| 34 #include <signal.h> |
| 35 #include <unistd.h> |
| 36 #endif // OS_MACOSX |
| 37 |
| 31 #if defined(USE_LINUX_BREAKPAD) | 38 #if defined(USE_LINUX_BREAKPAD) |
| 32 #include "chrome/app/breakpad_linux.h" | 39 #include "chrome/app/breakpad_linux.h" |
| 33 #endif | 40 #endif |
| 34 | 41 |
| 42 #if defined(OS_MACOSX) |
| 43 namespace { |
| 44 |
| 45 // TODO(viettrungluu): crbug.com/28547: The following signal handling is needed, |
| 46 // as a stopgap, to avoid leaking due to not releasing Breakpad properly. |
| 47 // Without this problem, this could all be eliminated. Remove when Breakpad is |
| 48 // fixed? |
| 49 // TODO(viettrungluu): Code taken from browser_main.cc (with a bit of editing). |
| 50 // The code should be properly shared (or this code should be eliminated). |
| 51 int g_shutdown_pipe_write_fd = -1; |
| 52 |
| 53 void SIGTERMHandler(int signal) { |
| 54 RAW_CHECK(signal == SIGTERM); |
| 55 RAW_LOG(INFO, "Handling SIGTERM in renderer."); |
| 56 |
| 57 // Reinstall the default handler. We had one shot at graceful shutdown. |
| 58 struct sigaction action; |
| 59 memset(&action, 0, sizeof(action)); |
| 60 action.sa_handler = SIG_DFL; |
| 61 CHECK(sigaction(signal, &action, NULL) == 0); |
| 62 |
| 63 RAW_CHECK(g_shutdown_pipe_write_fd != -1); |
| 64 size_t bytes_written = 0; |
| 65 do { |
| 66 int rv = HANDLE_EINTR( |
| 67 write(g_shutdown_pipe_write_fd, |
| 68 reinterpret_cast<const char*>(&signal) + bytes_written, |
| 69 sizeof(signal) - bytes_written)); |
| 70 RAW_CHECK(rv >= 0); |
| 71 bytes_written += rv; |
| 72 } while (bytes_written < sizeof(signal)); |
| 73 |
| 74 RAW_LOG(INFO, "Wrote signal to shutdown pipe."); |
| 75 } |
| 76 |
| 77 class ShutdownDetector : public PlatformThread::Delegate { |
| 78 public: |
| 79 explicit ShutdownDetector(int shutdown_fd) : shutdown_fd_(shutdown_fd) { |
| 80 CHECK(shutdown_fd_ != -1); |
| 81 } |
| 82 |
| 83 virtual void ThreadMain() { |
| 84 int signal; |
| 85 size_t bytes_read = 0; |
| 86 ssize_t ret; |
| 87 do { |
| 88 ret = HANDLE_EINTR( |
| 89 read(shutdown_fd_, |
| 90 reinterpret_cast<char*>(&signal) + bytes_read, |
| 91 sizeof(signal) - bytes_read)); |
| 92 if (ret < 0) { |
| 93 NOTREACHED() << "Unexpected error: " << strerror(errno); |
| 94 break; |
| 95 } else if (ret == 0) { |
| 96 NOTREACHED() << "Unexpected closure of shutdown pipe."; |
| 97 break; |
| 98 } |
| 99 bytes_read += ret; |
| 100 } while (bytes_read < sizeof(signal)); |
| 101 |
| 102 if (bytes_read == sizeof(signal)) |
| 103 LOG(INFO) << "Handling shutdown for signal " << signal << "."; |
| 104 else |
| 105 LOG(INFO) << "Handling shutdown for unknown signal."; |
| 106 |
| 107 // Clean up Breakpad if necessary. |
| 108 if (IsCrashReporterEnabled()) { |
| 109 LOG(INFO) << "Cleaning up Breakpad."; |
| 110 DestructCrashReporter(); |
| 111 } else { |
| 112 LOG(INFO) << "Breakpad not enabled; no clean-up needed."; |
| 113 } |
| 114 |
| 115 // Something went seriously wrong, so get out. |
| 116 if (bytes_read != sizeof(signal)) { |
| 117 LOG(WARNING) << "Failed to get signal. Quitting ungracefully."; |
| 118 _exit(1); |
| 119 } |
| 120 |
| 121 // Re-raise the signal. |
| 122 kill(getpid(), signal); |
| 123 |
| 124 // The signal may be handled on another thread. Give that a chance to |
| 125 // happen. |
| 126 sleep(3); |
| 127 |
| 128 // 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 |
| 130 // 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. |
| 132 // This mechanism isn't a de jure standard, but even in the worst case, it |
| 133 // should at least result in an immediate exit. |
| 134 LOG(WARNING) << "Still here, exiting really ungracefully."; |
| 135 _exit(signal | (1 << 7)); |
| 136 } |
| 137 |
| 138 private: |
| 139 const int shutdown_fd_; |
| 140 |
| 141 DISALLOW_COPY_AND_ASSIGN(ShutdownDetector); |
| 142 }; |
| 143 |
| 144 } // namespace |
| 145 #endif // OS_MACOSX |
| 146 |
| 35 // This function provides some ways to test crash and assertion handling | 147 // This function provides some ways to test crash and assertion handling |
| 36 // behavior of the renderer. | 148 // behavior of the renderer. |
| 37 static void HandleRendererErrorTestParameters(const CommandLine& command_line) { | 149 static void HandleRendererErrorTestParameters(const CommandLine& command_line) { |
| 38 // This parameter causes an assertion. | 150 // This parameter causes an assertion. |
| 39 if (command_line.HasSwitch(switches::kRendererAssertTest)) { | 151 if (command_line.HasSwitch(switches::kRendererAssertTest)) { |
| 40 DCHECK(false); | 152 DCHECK(false); |
| 41 } | 153 } |
| 42 | 154 |
| 43 // This parameter causes a null pointer crash (crash reporter trigger). | 155 // This parameter causes a null pointer crash (crash reporter trigger). |
| 44 if (command_line.HasSwitch(switches::kRendererCrashTest)) { | 156 if (command_line.HasSwitch(switches::kRendererCrashTest)) { |
| 45 int* bad_pointer = NULL; | 157 int* bad_pointer = NULL; |
| 46 *bad_pointer = 0; | 158 *bad_pointer = 0; |
| 47 } | 159 } |
| 48 | 160 |
| 49 if (command_line.HasSwitch(switches::kRendererStartupDialog)) { | 161 if (command_line.HasSwitch(switches::kRendererStartupDialog)) { |
| 50 ChildProcess::WaitForDebugger(L"Renderer"); | 162 ChildProcess::WaitForDebugger(L"Renderer"); |
| 51 } | 163 } |
| 52 } | 164 } |
| 53 | 165 |
| 54 // mainline routine for running as the Renderer process | 166 // mainline routine for running as the Renderer process |
| 55 int RendererMain(const MainFunctionParams& parameters) { | 167 int RendererMain(const MainFunctionParams& parameters) { |
| 56 const CommandLine& parsed_command_line = parameters.command_line_; | 168 const CommandLine& parsed_command_line = parameters.command_line_; |
| 57 base::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool_; | 169 base::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool_; |
| 58 | 170 |
| 171 #if defined(OS_MACOSX) |
| 172 // TODO(viettrungluu): Code taken from browser_main.cc. |
| 173 int pipefd[2]; |
| 174 int ret = pipe(pipefd); |
| 175 if (ret < 0) { |
| 176 PLOG(DFATAL) << "Failed to create pipe"; |
| 177 } else { |
| 178 int shutdown_pipe_read_fd = pipefd[0]; |
| 179 g_shutdown_pipe_write_fd = pipefd[1]; |
| 180 const size_t kShutdownDetectorThreadStackSize = 4096; |
| 181 if (!PlatformThread::CreateNonJoinable( |
| 182 kShutdownDetectorThreadStackSize, |
| 183 new ShutdownDetector(shutdown_pipe_read_fd))) { |
| 184 LOG(DFATAL) << "Failed to create shutdown detector task."; |
| 185 } |
| 186 } |
| 187 |
| 188 // crbug.com/28547: When Breakpad is in use, handle SIGTERM to avoid leaking |
| 189 // Mach ports. |
| 190 struct sigaction action; |
| 191 memset(&action, 0, sizeof(action)); |
| 192 action.sa_handler = SIGTERMHandler; |
| 193 CHECK(sigaction(SIGTERM, &action, NULL) == 0); |
| 194 #endif // OS_MACOSX |
| 195 |
| 59 #if defined(USE_LINUX_BREAKPAD) | 196 #if defined(USE_LINUX_BREAKPAD) |
| 60 // Needs to be called after we have chrome::DIR_USER_DATA. | 197 // Needs to be called after we have chrome::DIR_USER_DATA. |
| 61 InitCrashReporter(); | 198 InitCrashReporter(); |
| 62 #endif | 199 #endif |
| 63 | 200 |
| 64 // Configure the network module so it has access to resources. | 201 // Configure the network module so it has access to resources. |
| 65 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider); | 202 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider); |
| 66 | 203 |
| 67 // This function allows pausing execution using the --renderer-startup-dialog | 204 // This function allows pausing execution using the --renderer-startup-dialog |
| 68 // flag allowing us to attach a debugger. | 205 // flag allowing us to attach a debugger. |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 | 273 |
| 137 if (run_loop) { | 274 if (run_loop) { |
| 138 if (pool) | 275 if (pool) |
| 139 pool->Recycle(); | 276 pool->Recycle(); |
| 140 MessageLoop::current()->Run(); | 277 MessageLoop::current()->Run(); |
| 141 } | 278 } |
| 142 } | 279 } |
| 143 platform.PlatformUninitialize(); | 280 platform.PlatformUninitialize(); |
| 144 return 0; | 281 return 0; |
| 145 } | 282 } |
| OLD | NEW |