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/renderer/chrome_render_process_observer.h" | 5 #include "chrome/renderer/chrome_render_process_observer.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/metrics/field_trial.h" | 9 #include "base/metrics/field_trial.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 29 matching lines...) Expand all Loading... |
40 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFontCache.h" | 40 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFontCache.h" |
41 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 41 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
42 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRuntimeFeatures.h" | 42 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRuntimeFeatures.h" |
43 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 43 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
44 #include "v8/include/v8.h" | 44 #include "v8/include/v8.h" |
45 | 45 |
46 #if defined(OS_WIN) | 46 #if defined(OS_WIN) |
47 #include "base/win/iat_patch_function.h" | 47 #include "base/win/iat_patch_function.h" |
48 #endif | 48 #endif |
49 | 49 |
| 50 #if defined(OS_MACOSX) |
| 51 #include "base/eintr_wrapper.h" |
| 52 #include "chrome/app/breakpad_mac.h" |
| 53 #endif |
| 54 |
50 using WebKit::WebCache; | 55 using WebKit::WebCache; |
51 using WebKit::WebCrossOriginPreflightResultCache; | 56 using WebKit::WebCrossOriginPreflightResultCache; |
52 using WebKit::WebFontCache; | 57 using WebKit::WebFontCache; |
53 using WebKit::WebRuntimeFeatures; | 58 using WebKit::WebRuntimeFeatures; |
54 | 59 |
55 namespace { | 60 namespace { |
56 | 61 |
57 static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; | 62 static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; |
58 | 63 |
59 class RendererResourceDelegate : public ResourceDispatcherDelegate { | 64 class RendererResourceDelegate : public ResourceDispatcherDelegate { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 // processed (because that message loop is stuck in V8). | 183 // processed (because that message loop is stuck in V8). |
179 // | 184 // |
180 // One could make the browser SIGKILL the renderers, but that leaves open a | 185 // One could make the browser SIGKILL the renderers, but that leaves open a |
181 // large window where a browser failure (or a user, manually terminating | 186 // large window where a browser failure (or a user, manually terminating |
182 // the browser because "it's stuck") will leave behind a process eating all | 187 // the browser because "it's stuck") will leave behind a process eating all |
183 // the CPU. | 188 // the CPU. |
184 // | 189 // |
185 // So, we install a filter on the channel so that we can process this event | 190 // So, we install a filter on the channel so that we can process this event |
186 // here and kill the process. | 191 // here and kill the process. |
187 | 192 |
| 193 #if defined(OS_MACOSX) |
| 194 // TODO(viettrungluu): crbug.com/28547: The following is needed, as a |
| 195 // stopgap, to avoid leaking due to not releasing Breakpad properly. |
| 196 // TODO(viettrungluu): Investigate why this is being called. |
| 197 if (IsCrashReporterEnabled()) { |
| 198 VLOG(1) << "Cleaning up Breakpad."; |
| 199 DestructCrashReporter(); |
| 200 } else { |
| 201 VLOG(1) << "Breakpad not enabled; no clean-up needed."; |
| 202 } |
| 203 #endif // OS_MACOSX |
| 204 |
188 _exit(0); | 205 _exit(0); |
189 } | 206 } |
190 }; | 207 }; |
191 #endif // OS_POSIX | 208 #endif // OS_POSIX |
192 | 209 |
| 210 #if defined(OS_MACOSX) |
| 211 // TODO(viettrungluu): crbug.com/28547: The following signal handling is needed, |
| 212 // as a stopgap, to avoid leaking due to not releasing Breakpad properly. |
| 213 // Without this problem, this could all be eliminated. Remove when Breakpad is |
| 214 // fixed? |
| 215 // TODO(viettrungluu): Code taken from browser_main.cc (with a bit of editing). |
| 216 // The code should be properly shared (or this code should be eliminated). |
| 217 int g_shutdown_pipe_write_fd = -1; |
| 218 |
| 219 void SIGTERMHandler(int signal) { |
| 220 RAW_CHECK(signal == SIGTERM); |
| 221 |
| 222 // Reinstall the default handler. We had one shot at graceful shutdown. |
| 223 struct sigaction action; |
| 224 memset(&action, 0, sizeof(action)); |
| 225 action.sa_handler = SIG_DFL; |
| 226 CHECK(sigaction(signal, &action, NULL) == 0); |
| 227 |
| 228 RAW_CHECK(g_shutdown_pipe_write_fd != -1); |
| 229 size_t bytes_written = 0; |
| 230 do { |
| 231 int rv = HANDLE_EINTR( |
| 232 write(g_shutdown_pipe_write_fd, |
| 233 reinterpret_cast<const char*>(&signal) + bytes_written, |
| 234 sizeof(signal) - bytes_written)); |
| 235 RAW_CHECK(rv >= 0); |
| 236 bytes_written += rv; |
| 237 } while (bytes_written < sizeof(signal)); |
| 238 } |
| 239 |
| 240 class ShutdownDetector : public base::PlatformThread::Delegate { |
| 241 public: |
| 242 explicit ShutdownDetector(int shutdown_fd) : shutdown_fd_(shutdown_fd) { |
| 243 CHECK(shutdown_fd_ != -1); |
| 244 } |
| 245 |
| 246 virtual void ThreadMain() { |
| 247 int signal; |
| 248 size_t bytes_read = 0; |
| 249 ssize_t ret; |
| 250 do { |
| 251 ret = HANDLE_EINTR( |
| 252 read(shutdown_fd_, |
| 253 reinterpret_cast<char*>(&signal) + bytes_read, |
| 254 sizeof(signal) - bytes_read)); |
| 255 if (ret < 0) { |
| 256 NOTREACHED() << "Unexpected error: " << strerror(errno); |
| 257 break; |
| 258 } else if (ret == 0) { |
| 259 NOTREACHED() << "Unexpected closure of shutdown pipe."; |
| 260 break; |
| 261 } |
| 262 bytes_read += ret; |
| 263 } while (bytes_read < sizeof(signal)); |
| 264 |
| 265 if (bytes_read == sizeof(signal)) |
| 266 VLOG(1) << "Handling shutdown for signal " << signal << "."; |
| 267 else |
| 268 VLOG(1) << "Handling shutdown for unknown signal."; |
| 269 |
| 270 // Clean up Breakpad if necessary. |
| 271 if (IsCrashReporterEnabled()) { |
| 272 VLOG(1) << "Cleaning up Breakpad."; |
| 273 DestructCrashReporter(); |
| 274 } else { |
| 275 VLOG(1) << "Breakpad not enabled; no clean-up needed."; |
| 276 } |
| 277 |
| 278 // Something went seriously wrong, so get out. |
| 279 if (bytes_read != sizeof(signal)) { |
| 280 LOG(WARNING) << "Failed to get signal. Quitting ungracefully."; |
| 281 _exit(1); |
| 282 } |
| 283 |
| 284 // Re-raise the signal. |
| 285 kill(getpid(), signal); |
| 286 |
| 287 // The signal may be handled on another thread. Give that a chance to |
| 288 // happen. |
| 289 sleep(3); |
| 290 |
| 291 // We really should be dead by now. For whatever reason, we're not. Exit |
| 292 // immediately, with the exit status set to the signal number with bit 8 |
| 293 // set. On the systems that we care about, this exit status is what is |
| 294 // normally used to indicate an exit by this signal's default handler. |
| 295 // This mechanism isn't a de jure standard, but even in the worst case, it |
| 296 // should at least result in an immediate exit. |
| 297 LOG(WARNING) << "Still here, exiting really ungracefully."; |
| 298 _exit(signal | (1 << 7)); |
| 299 } |
| 300 |
| 301 private: |
| 302 const int shutdown_fd_; |
| 303 |
| 304 DISALLOW_COPY_AND_ASSIGN(ShutdownDetector); |
| 305 }; |
| 306 #endif // OS_MACOSX |
| 307 |
193 } // namespace | 308 } // namespace |
194 | 309 |
195 bool ChromeRenderProcessObserver::is_incognito_process_ = false; | 310 bool ChromeRenderProcessObserver::is_incognito_process_ = false; |
196 | 311 |
197 ChromeRenderProcessObserver::ChromeRenderProcessObserver( | 312 ChromeRenderProcessObserver::ChromeRenderProcessObserver( |
198 chrome::ChromeContentRendererClient* client) | 313 chrome::ChromeContentRendererClient* client) |
199 : client_(client), | 314 : client_(client), |
200 clear_cache_pending_(false) { | 315 clear_cache_pending_(false) { |
201 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 316 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
202 if (command_line.HasSwitch(switches::kEnableWatchdog)) { | 317 if (command_line.HasSwitch(switches::kEnableWatchdog)) { |
203 // TODO(JAR): Need to implement renderer IO msgloop watchdog. | 318 // TODO(JAR): Need to implement renderer IO msgloop watchdog. |
204 } | 319 } |
205 | 320 |
206 if (command_line.HasSwitch(switches::kDumpHistogramsOnExit)) { | 321 if (command_line.HasSwitch(switches::kDumpHistogramsOnExit)) { |
207 base::StatisticsRecorder::set_dump_on_exit(true); | 322 base::StatisticsRecorder::set_dump_on_exit(true); |
208 } | 323 } |
209 | 324 |
210 RenderThread* thread = RenderThread::current(); | 325 RenderThread* thread = RenderThread::current(); |
211 resource_delegate_.reset(new RendererResourceDelegate()); | 326 resource_delegate_.reset(new RendererResourceDelegate()); |
212 thread->resource_dispatcher()->set_delegate(resource_delegate_.get()); | 327 thread->resource_dispatcher()->set_delegate(resource_delegate_.get()); |
213 | 328 |
214 #if defined(OS_POSIX) | 329 #if defined(OS_POSIX) |
215 thread->AddFilter(new SuicideOnChannelErrorFilter()); | 330 thread->AddFilter(new SuicideOnChannelErrorFilter()); |
216 #endif | 331 #endif |
217 | 332 |
| 333 #if defined(OS_MACOSX) |
| 334 // TODO(viettrungluu): Code taken from browser_main.cc. |
| 335 int pipefd[2]; |
| 336 int ret = pipe(pipefd); |
| 337 if (ret < 0) { |
| 338 PLOG(DFATAL) << "Failed to create pipe"; |
| 339 } else { |
| 340 int shutdown_pipe_read_fd = pipefd[0]; |
| 341 g_shutdown_pipe_write_fd = pipefd[1]; |
| 342 const size_t kShutdownDetectorThreadStackSize = 4096; |
| 343 if (!base::PlatformThread::CreateNonJoinable( |
| 344 kShutdownDetectorThreadStackSize, |
| 345 new ShutdownDetector(shutdown_pipe_read_fd))) { |
| 346 LOG(DFATAL) << "Failed to create shutdown detector task."; |
| 347 } |
| 348 } |
| 349 |
| 350 // crbug.com/28547: When Breakpad is in use, handle SIGTERM to avoid leaking |
| 351 // Mach ports. |
| 352 struct sigaction action; |
| 353 memset(&action, 0, sizeof(action)); |
| 354 action.sa_handler = SIGTERMHandler; |
| 355 CHECK(sigaction(SIGTERM, &action, NULL) == 0); |
| 356 #endif |
| 357 |
218 // Configure modules that need access to resources. | 358 // Configure modules that need access to resources. |
219 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider); | 359 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider); |
220 | 360 |
221 #if defined(OS_WIN) | 361 #if defined(OS_WIN) |
222 // Need to patch a few functions for font loading to work correctly. | 362 // Need to patch a few functions for font loading to work correctly. |
223 FilePath pdf; | 363 FilePath pdf; |
224 if (PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf) && | 364 if (PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf) && |
225 file_util::PathExists(pdf)) { | 365 file_util::PathExists(pdf)) { |
226 g_iat_patch_createdca.Patch( | 366 g_iat_patch_createdca.Patch( |
227 pdf.value().c_str(), "gdi32.dll", "CreateDCA", CreateDCAPatch); | 367 pdf.value().c_str(), "gdi32.dll", "CreateDCA", CreateDCAPatch); |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 if (client_) | 554 if (client_) |
415 client_->OnPurgeMemory(); | 555 client_->OnPurgeMemory(); |
416 } | 556 } |
417 | 557 |
418 void ChromeRenderProcessObserver::ExecutePendingClearCache() { | 558 void ChromeRenderProcessObserver::ExecutePendingClearCache() { |
419 if (clear_cache_pending_) { | 559 if (clear_cache_pending_) { |
420 clear_cache_pending_ = false; | 560 clear_cache_pending_ = false; |
421 WebCache::clear(); | 561 WebCache::clear(); |
422 } | 562 } |
423 } | 563 } |
OLD | NEW |