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 | |
55 using WebKit::WebCache; | 50 using WebKit::WebCache; |
56 using WebKit::WebCrossOriginPreflightResultCache; | 51 using WebKit::WebCrossOriginPreflightResultCache; |
57 using WebKit::WebFontCache; | 52 using WebKit::WebFontCache; |
58 using WebKit::WebRuntimeFeatures; | 53 using WebKit::WebRuntimeFeatures; |
59 | 54 |
60 namespace { | 55 namespace { |
61 | 56 |
62 static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; | 57 static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */; |
63 | 58 |
64 class RendererResourceDelegate : public ResourceDispatcherDelegate { | 59 class RendererResourceDelegate : public ResourceDispatcherDelegate { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 // processed (because that message loop is stuck in V8). | 178 // processed (because that message loop is stuck in V8). |
184 // | 179 // |
185 // One could make the browser SIGKILL the renderers, but that leaves open a | 180 // One could make the browser SIGKILL the renderers, but that leaves open a |
186 // large window where a browser failure (or a user, manually terminating | 181 // large window where a browser failure (or a user, manually terminating |
187 // the browser because "it's stuck") will leave behind a process eating all | 182 // the browser because "it's stuck") will leave behind a process eating all |
188 // the CPU. | 183 // the CPU. |
189 // | 184 // |
190 // So, we install a filter on the channel so that we can process this event | 185 // So, we install a filter on the channel so that we can process this event |
191 // here and kill the process. | 186 // here and kill the process. |
192 | 187 |
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 | |
205 _exit(0); | 188 _exit(0); |
206 } | 189 } |
207 }; | 190 }; |
208 #endif // OS_POSIX | 191 #endif // OS_POSIX |
209 | 192 |
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 | |
308 } // namespace | 193 } // namespace |
309 | 194 |
310 bool ChromeRenderProcessObserver::is_incognito_process_ = false; | 195 bool ChromeRenderProcessObserver::is_incognito_process_ = false; |
311 | 196 |
312 ChromeRenderProcessObserver::ChromeRenderProcessObserver( | 197 ChromeRenderProcessObserver::ChromeRenderProcessObserver( |
313 chrome::ChromeContentRendererClient* client) | 198 chrome::ChromeContentRendererClient* client) |
314 : client_(client) { | 199 : client_(client) { |
315 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 200 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
316 if (command_line.HasSwitch(switches::kEnableWatchdog)) { | 201 if (command_line.HasSwitch(switches::kEnableWatchdog)) { |
317 // TODO(JAR): Need to implement renderer IO msgloop watchdog. | 202 // TODO(JAR): Need to implement renderer IO msgloop watchdog. |
318 } | 203 } |
319 | 204 |
320 if (command_line.HasSwitch(switches::kDumpHistogramsOnExit)) { | 205 if (command_line.HasSwitch(switches::kDumpHistogramsOnExit)) { |
321 base::StatisticsRecorder::set_dump_on_exit(true); | 206 base::StatisticsRecorder::set_dump_on_exit(true); |
322 } | 207 } |
323 | 208 |
324 RenderThread* thread = RenderThread::current(); | 209 RenderThread* thread = RenderThread::current(); |
325 resource_delegate_.reset(new RendererResourceDelegate()); | 210 resource_delegate_.reset(new RendererResourceDelegate()); |
326 thread->resource_dispatcher()->set_delegate(resource_delegate_.get()); | 211 thread->resource_dispatcher()->set_delegate(resource_delegate_.get()); |
327 | 212 |
328 #if defined(OS_POSIX) | 213 #if defined(OS_POSIX) |
329 thread->AddFilter(new SuicideOnChannelErrorFilter()); | 214 thread->AddFilter(new SuicideOnChannelErrorFilter()); |
330 #endif | 215 #endif |
331 | 216 |
332 #if defined(OS_MACOSX) | |
333 // TODO(viettrungluu): Code taken from browser_main.cc. | |
334 int pipefd[2]; | |
335 int ret = pipe(pipefd); | |
336 if (ret < 0) { | |
337 PLOG(DFATAL) << "Failed to create pipe"; | |
338 } else { | |
339 int shutdown_pipe_read_fd = pipefd[0]; | |
340 g_shutdown_pipe_write_fd = pipefd[1]; | |
341 const size_t kShutdownDetectorThreadStackSize = 4096; | |
342 if (!base::PlatformThread::CreateNonJoinable( | |
343 kShutdownDetectorThreadStackSize, | |
344 new ShutdownDetector(shutdown_pipe_read_fd))) { | |
345 LOG(DFATAL) << "Failed to create shutdown detector task."; | |
346 } | |
347 } | |
348 | |
349 // crbug.com/28547: When Breakpad is in use, handle SIGTERM to avoid leaking | |
350 // Mach ports. | |
351 struct sigaction action; | |
352 memset(&action, 0, sizeof(action)); | |
353 action.sa_handler = SIGTERMHandler; | |
354 CHECK(sigaction(SIGTERM, &action, NULL) == 0); | |
355 #endif | |
356 | |
357 // Configure modules that need access to resources. | 217 // Configure modules that need access to resources. |
358 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider); | 218 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider); |
359 | 219 |
360 #if defined(OS_WIN) | 220 #if defined(OS_WIN) |
361 // Need to patch a few functions for font loading to work correctly. | 221 // Need to patch a few functions for font loading to work correctly. |
362 FilePath pdf; | 222 FilePath pdf; |
363 if (PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf) && | 223 if (PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf) && |
364 file_util::PathExists(pdf)) { | 224 file_util::PathExists(pdf)) { |
365 g_iat_patch_createdca.Patch( | 225 g_iat_patch_createdca.Patch( |
366 pdf.value().c_str(), "gdi32.dll", "CreateDCA", CreateDCAPatch); | 226 pdf.value().c_str(), "gdi32.dll", "CreateDCA", CreateDCAPatch); |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 } | 402 } |
543 | 403 |
544 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC) | 404 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC) |
545 // Tell tcmalloc to release any free pages it's still holding. | 405 // Tell tcmalloc to release any free pages it's still holding. |
546 MallocExtension::instance()->ReleaseFreeMemory(); | 406 MallocExtension::instance()->ReleaseFreeMemory(); |
547 #endif | 407 #endif |
548 | 408 |
549 if (client_) | 409 if (client_) |
550 client_->OnPurgeMemory(); | 410 client_->OnPurgeMemory(); |
551 } | 411 } |
OLD | NEW |