Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: content/browser/renderer_host/render_view_host_impl.cc

Issue 10381073: Revert 132407 - Fixing a problem, where a hung renderer process is not killed when navigating away (Closed) Base URL: svn://svn.chromium.org/chrome/branches/1130/src/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "content/browser/renderer_host/render_view_host_impl.h" 5 #include "content/browser/renderer_host/render_view_host_impl.h"
6 6
7 #include <set> 7 #include <set>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/i18n/rtl.h" 13 #include "base/i18n/rtl.h"
14 #include "base/json/json_reader.h" 14 #include "base/json/json_reader.h"
15 #include "base/message_loop.h" 15 #include "base/message_loop.h"
16 #include "base/metrics/histogram.h"
17 #include "base/stl_util.h" 16 #include "base/stl_util.h"
18 #include "base/string_util.h" 17 #include "base/string_util.h"
19 #include "base/time.h" 18 #include "base/time.h"
20 #include "base/utf_string_conversions.h" 19 #include "base/utf_string_conversions.h"
21 #include "base/values.h" 20 #include "base/values.h"
22 #if defined(OS_WIN) 21 #if defined(OS_WIN)
23 #include "base/win/windows_version.h" 22 #include "base/win/windows_version.h"
24 #endif 23 #endif
25 #include "content/browser/child_process_security_policy_impl.h" 24 #include "content/browser/child_process_security_policy_impl.h"
26 #include "content/browser/cross_site_request_manager.h" 25 #include "content/browser/cross_site_request_manager.h"
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 waiting_for_drag_context_response_(false), 141 waiting_for_drag_context_response_(false),
143 enabled_bindings_(0), 142 enabled_bindings_(0),
144 guest_(false), 143 guest_(false),
145 pending_request_id_(-1), 144 pending_request_id_(-1),
146 navigations_suspended_(false), 145 navigations_suspended_(false),
147 suspended_nav_message_(NULL), 146 suspended_nav_message_(NULL),
148 is_swapped_out_(swapped_out), 147 is_swapped_out_(swapped_out),
149 run_modal_reply_msg_(NULL), 148 run_modal_reply_msg_(NULL),
150 is_waiting_for_beforeunload_ack_(false), 149 is_waiting_for_beforeunload_ack_(false),
151 is_waiting_for_unload_ack_(false), 150 is_waiting_for_unload_ack_(false),
152 has_timed_out_on_unload_(false),
153 unload_ack_is_for_cross_site_transition_(false), 151 unload_ack_is_for_cross_site_transition_(false),
154 are_javascript_messages_suppressed_(false), 152 are_javascript_messages_suppressed_(false),
155 sudden_termination_allowed_(false), 153 sudden_termination_allowed_(false),
156 session_storage_namespace_( 154 session_storage_namespace_(
157 static_cast<SessionStorageNamespaceImpl*>(session_storage)), 155 static_cast<SessionStorageNamespaceImpl*>(session_storage)),
158 save_accessibility_tree_for_testing_(false), 156 save_accessibility_tree_for_testing_(false),
159 send_accessibility_updated_notifications_(false), 157 send_accessibility_updated_notifications_(false),
160 render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING) { 158 render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING) {
161 if (!session_storage_namespace_) { 159 if (!session_storage_namespace_) {
162 DOMStorageContext* dom_storage_context = 160 DOMStorageContext* dom_storage_context =
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 // (if there was a cross-site "close" request pending when the user clicked 398 // (if there was a cross-site "close" request pending when the user clicked
401 // the close button). We want to keep the "for cross site" flag only if 399 // the close button). We want to keep the "for cross site" flag only if
402 // both the old and the new ones are also for cross site. 400 // both the old and the new ones are also for cross site.
403 unload_ack_is_for_cross_site_transition_ = 401 unload_ack_is_for_cross_site_transition_ =
404 unload_ack_is_for_cross_site_transition_ && for_cross_site_transition; 402 unload_ack_is_for_cross_site_transition_ && for_cross_site_transition;
405 } else { 403 } else {
406 // Start the hang monitor in case the renderer hangs in the beforeunload 404 // Start the hang monitor in case the renderer hangs in the beforeunload
407 // handler. 405 // handler.
408 is_waiting_for_beforeunload_ack_ = true; 406 is_waiting_for_beforeunload_ack_ = true;
409 unload_ack_is_for_cross_site_transition_ = for_cross_site_transition; 407 unload_ack_is_for_cross_site_transition_ = for_cross_site_transition;
410 // Increment the in-flight event count, to ensure that input events won't
411 // cancel the timeout timer.
412 increment_in_flight_event_count();
413 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS)); 408 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
414 send_should_close_start_time_ = base::TimeTicks::Now(); 409 send_should_close_start_time_ = base::TimeTicks::Now();
415 Send(new ViewMsg_ShouldClose(GetRoutingID())); 410 Send(new ViewMsg_ShouldClose(GetRoutingID()));
416 } 411 }
417 } 412 }
418 413
419 void RenderViewHostImpl::SwapOut(int new_render_process_host_id, 414 void RenderViewHostImpl::SwapOut(int new_render_process_host_id,
420 int new_request_id) { 415 int new_request_id) {
421 // This will be set back to false in OnSwapOutACK, just before we replace 416 // This will be set back to false in OnSwapOutACK, just before we replace
422 // this RVH with the pending RVH. 417 // this RVH with the pending RVH.
423 is_waiting_for_unload_ack_ = true; 418 is_waiting_for_unload_ack_ = true;
424 // Start the hang monitor in case the renderer hangs in the unload handler. 419 // Start the hang monitor in case the renderer hangs in the unload handler.
425 // Increment the in-flight event count, to ensure that input events won't
426 // cancel the timeout timer.
427 increment_in_flight_event_count();
428 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS)); 420 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
429 421
430 ViewMsg_SwapOut_Params params; 422 ViewMsg_SwapOut_Params params;
431 params.closing_process_id = GetProcess()->GetID(); 423 params.closing_process_id = GetProcess()->GetID();
432 params.closing_route_id = GetRoutingID(); 424 params.closing_route_id = GetRoutingID();
433 params.new_render_process_host_id = new_render_process_host_id; 425 params.new_render_process_host_id = new_render_process_host_id;
434 params.new_request_id = new_request_id; 426 params.new_request_id = new_request_id;
435 if (IsRenderViewLive()) { 427 if (IsRenderViewLive()) {
436 Send(new ViewMsg_SwapOut(GetRoutingID(), params)); 428 Send(new ViewMsg_SwapOut(GetRoutingID(), params));
437 } else { 429 } else {
438 // This RenderViewHost doesn't have a live renderer, so just skip the unload 430 // This RenderViewHost doesn't have a live renderer, so just skip the unload
439 // event. We must notify the ResourceDispatcherHost on the IO thread, 431 // event. We must notify the ResourceDispatcherHost on the IO thread,
440 // which we will do through the RenderProcessHost's widget helper. 432 // which we will do through the RenderProcessHost's widget helper.
441 GetProcess()->SimulateSwapOutACK(params); 433 GetProcess()->CrossSiteSwapOutACK(params);
442 } 434 }
443 } 435 }
444 436
445 void RenderViewHostImpl::OnSwapOutACK(bool timed_out) { 437 void RenderViewHostImpl::OnSwapOutACK() {
446 // Stop the hang monitor now that the unload handler has finished. 438 // Stop the hang monitor now that the unload handler has finished.
447 decrement_in_flight_event_count();
448 StopHangMonitorTimeout(); 439 StopHangMonitorTimeout();
449 is_waiting_for_unload_ack_ = false; 440 is_waiting_for_unload_ack_ = false;
450 has_timed_out_on_unload_ = timed_out;
451 delegate_->SwappedOut(this); 441 delegate_->SwappedOut(this);
452 } 442 }
453 443
454 void RenderViewHostImpl::WasSwappedOut() { 444 void RenderViewHostImpl::WasSwappedOut() {
455 // Don't bother reporting hung state anymore. 445 // Don't bother reporting hung state anymore.
456 StopHangMonitorTimeout(); 446 StopHangMonitorTimeout();
457 447
458 // If we have timed out on running the unload handler, we consider
459 // the process hung and we should terminate it if there are no other tabs
460 // using the process. If there are other views using this process, the
461 // unresponsive renderer timeout will catch it.
462 bool hung = has_timed_out_on_unload_;
463
464 // Now that we're no longer the active RVH in the tab, start filtering out 448 // Now that we're no longer the active RVH in the tab, start filtering out
465 // most IPC messages. Usually the renderer will have stopped sending 449 // most IPC messages. Usually the renderer will have stopped sending
466 // messages as of OnSwapOutACK. However, we may have timed out waiting 450 // messages as of OnSwapOutACK. However, we may have timed out waiting
467 // for that message, and additional IPC messages may keep streaming in. 451 // for that message, and additional IPC messages may keep streaming in.
468 // We filter them out, as long as that won't cause problems (e.g., we 452 // We filter them out, as long as that won't cause problems (e.g., we
469 // still allow synchronous messages through). 453 // still allow synchronous messages through).
470 SetSwappedOut(true); 454 SetSwappedOut(true);
471 455
472 // If we are not running the renderer in process and no other tab is using
473 // the hung process, kill it, assuming it is a real process (unit tests don't
474 // have real processes).
475 if (hung) {
476 base::ProcessHandle process_handle = GetProcess()->GetHandle();
477 int views = 0;
478
479 // Count the number of widget hosts for the process, which is equivalent to
480 // views using the process as of this writing.
481 content::RenderProcessHost::RenderWidgetHostsIterator iter(
482 GetProcess()->GetRenderWidgetHostsIterator());
483 for (; !iter.IsAtEnd(); iter.Advance())
484 ++views;
485
486 if (!content::RenderProcessHost::run_renderer_in_process() &&
487 process_handle && views <= 1) {
488 // We expect the delegate for this RVH to be WebContents, as it is the
489 // only class that swaps out render view hosts on navigation.
490 DCHECK_EQ(delegate_->GetRenderViewType(),
491 content::VIEW_TYPE_WEB_CONTENTS);
492
493 // Kill the process only if WebContents sets SuddenTerminationAllowed,
494 // which indicates that the timer has expired.
495 // This is not the case if we load data URLs or about:blank. The reason
496 // is that there is no network requests and this code is hit without
497 // setting the unresponsiveness timer. This allows a corner case where a
498 // navigation to a data URL will leave a process running, if the
499 // beforeunload handler completes fine, but the unload handler hangs.
500 // At this time, the complexity to solve this edge case is not worthwhile.
501 if (SuddenTerminationAllowed()) {
502 base::KillProcess(process_handle, content::RESULT_CODE_HUNG, false);
503 // Log a histogram point to help us diagnose how many of those kills
504 // we have performed. 1 is the enum value for RendererType Normal for
505 // the histogram.
506 UMA_HISTOGRAM_PERCENTAGE(
507 "BrowserRenderProcessHost.ChildKillsUnresponsive", 1);
508 }
509 }
510 }
511
512 // Inform the renderer that it can exit if no one else is using it. 456 // Inform the renderer that it can exit if no one else is using it.
513 Send(new ViewMsg_WasSwappedOut(GetRoutingID())); 457 Send(new ViewMsg_WasSwappedOut(GetRoutingID()));
514 } 458 }
515 459
516 void RenderViewHostImpl::ClosePage() { 460 void RenderViewHostImpl::ClosePage() {
517 // Start the hang monitor in case the renderer hangs in the unload handler. 461 // Start the hang monitor in case the renderer hangs in the unload handler.
518 is_waiting_for_unload_ack_ = true; 462 is_waiting_for_unload_ack_ = true;
519 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS)); 463 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
520 464
521 if (IsRenderViewLive()) { 465 if (IsRenderViewLive()) {
522 // Since we are sending an IPC message to the renderer, increase the event
523 // count to prevent the hang monitor timeout from being stopped by input
524 // event acknowledgements.
525 increment_in_flight_event_count();
526
527 // TODO(creis): Should this be moved to Shutdown? It may not be called for 466 // TODO(creis): Should this be moved to Shutdown? It may not be called for
528 // RenderViewHosts that have been swapped out. 467 // RenderViewHosts that have been swapped out.
529 content::NotificationService::current()->Notify( 468 content::NotificationService::current()->Notify(
530 content::NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW, 469 content::NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW,
531 content::Source<RenderViewHost>(this), 470 content::Source<RenderViewHost>(this),
532 content::NotificationService::NoDetails()); 471 content::NotificationService::NoDetails());
533 472
534 Send(new ViewMsg_ClosePage(GetRoutingID())); 473 Send(new ViewMsg_ClosePage(GetRoutingID()));
535 } else { 474 } else {
536 // This RenderViewHost doesn't have a live renderer, so just skip the unload 475 // This RenderViewHost doesn't have a live renderer, so just skip the unload
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 loop->Run(); 643 loop->Run();
705 return observer.value()->DeepCopy(); 644 return observer.value()->DeepCopy();
706 } 645 }
707 646
708 void RenderViewHostImpl::JavaScriptDialogClosed(IPC::Message* reply_msg, 647 void RenderViewHostImpl::JavaScriptDialogClosed(IPC::Message* reply_msg,
709 bool success, 648 bool success,
710 const string16& user_input) { 649 const string16& user_input) {
711 GetProcess()->SetIgnoreInputEvents(false); 650 GetProcess()->SetIgnoreInputEvents(false);
712 bool is_waiting = 651 bool is_waiting =
713 is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_; 652 is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_;
714
715 // If we are executing as part of (before)unload event handling, we don't
716 // want to use the regular hung_renderer_delay_ms_ if the user has agreed to
717 // leave the current page. In this case, use the regular timeout value used
718 // during the (before)unload handling.
719 if (is_waiting) 653 if (is_waiting)
720 StartHangMonitorTimeout(TimeDelta::FromMilliseconds( 654 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
721 success ? kUnloadTimeoutMS : hung_renderer_delay_ms_));
722 655
723 ViewHostMsg_RunJavaScriptMessage::WriteReplyParams(reply_msg, 656 ViewHostMsg_RunJavaScriptMessage::WriteReplyParams(reply_msg,
724 success, user_input); 657 success, user_input);
725 Send(reply_msg); 658 Send(reply_msg);
726 659
727 // If we are waiting for an unload or beforeunload ack and the user has 660 // If we are waiting for an unload or beforeunload ack and the user has
728 // suppressed messages, kill the tab immediately; a page that's spamming 661 // suppressed messages, kill the tab immediately; a page that's spamming
729 // alerts in onbeforeunload is presumably malicious, so there's no point in 662 // alerts in onbeforeunload is presumably malicious, so there's no point in
730 // continuing to run its script and dragging out the process. 663 // continuing to run its script and dragging out the process.
731 // This must be done after sending the reply since RenderView can't close 664 // This must be done after sending the reply since RenderView can't close
(...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after
1420 } 1353 }
1421 1354
1422 void RenderViewHostImpl::OnUserGesture() { 1355 void RenderViewHostImpl::OnUserGesture() {
1423 delegate_->OnUserGesture(); 1356 delegate_->OnUserGesture();
1424 } 1357 }
1425 1358
1426 void RenderViewHostImpl::OnMsgShouldCloseACK( 1359 void RenderViewHostImpl::OnMsgShouldCloseACK(
1427 bool proceed, 1360 bool proceed,
1428 const base::TimeTicks& renderer_before_unload_start_time, 1361 const base::TimeTicks& renderer_before_unload_start_time,
1429 const base::TimeTicks& renderer_before_unload_end_time) { 1362 const base::TimeTicks& renderer_before_unload_end_time) {
1430 decrement_in_flight_event_count();
1431 StopHangMonitorTimeout(); 1363 StopHangMonitorTimeout();
1432 // If this renderer navigated while the beforeunload request was in flight, we 1364 // If this renderer navigated while the beforeunload request was in flight, we
1433 // may have cleared this state in OnMsgNavigate, in which case we can ignore 1365 // may have cleared this state in OnMsgNavigate, in which case we can ignore
1434 // this message. 1366 // this message.
1435 if (!is_waiting_for_beforeunload_ack_ || is_swapped_out_) 1367 if (!is_waiting_for_beforeunload_ack_ || is_swapped_out_)
1436 return; 1368 return;
1437 1369
1438 is_waiting_for_beforeunload_ack_ = false; 1370 is_waiting_for_beforeunload_ack_ = false;
1439 1371
1440 RenderViewHostDelegate::RendererManagement* management_delegate = 1372 RenderViewHostDelegate::RendererManagement* management_delegate =
(...skipping 21 matching lines...) Expand all
1462 unload_ack_is_for_cross_site_transition_, proceed, 1394 unload_ack_is_for_cross_site_transition_, proceed,
1463 before_unload_end_time); 1395 before_unload_end_time);
1464 } 1396 }
1465 1397
1466 // If canceled, notify the delegate to cancel its pending navigation entry. 1398 // If canceled, notify the delegate to cancel its pending navigation entry.
1467 if (!proceed) 1399 if (!proceed)
1468 delegate_->DidCancelLoading(); 1400 delegate_->DidCancelLoading();
1469 } 1401 }
1470 1402
1471 void RenderViewHostImpl::OnMsgClosePageACK() { 1403 void RenderViewHostImpl::OnMsgClosePageACK() {
1472 decrement_in_flight_event_count();
1473 ClosePageIgnoringUnloadEvents(); 1404 ClosePageIgnoringUnloadEvents();
1474 } 1405 }
1475 1406
1476 void RenderViewHostImpl::NotifyRendererUnresponsive() { 1407 void RenderViewHostImpl::NotifyRendererUnresponsive() {
1477 delegate_->RendererUnresponsive( 1408 delegate_->RendererUnresponsive(
1478 this, is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_); 1409 this, is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_);
1479 } 1410 }
1480 1411
1481 void RenderViewHostImpl::NotifyRendererResponsive() { 1412 void RenderViewHostImpl::NotifyRendererResponsive() {
1482 delegate_->RendererResponsive(this); 1413 delegate_->RendererResponsive(this);
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
1834 } 1765 }
1835 1766
1836 void RenderViewHostImpl::SetSwappedOut(bool is_swapped_out) { 1767 void RenderViewHostImpl::SetSwappedOut(bool is_swapped_out) {
1837 is_swapped_out_ = is_swapped_out; 1768 is_swapped_out_ = is_swapped_out;
1838 1769
1839 // Whenever we change swap out state, we should not be waiting for 1770 // Whenever we change swap out state, we should not be waiting for
1840 // beforeunload or unload acks. We clear them here to be safe, since they 1771 // beforeunload or unload acks. We clear them here to be safe, since they
1841 // can cause navigations to be ignored in OnMsgNavigate. 1772 // can cause navigations to be ignored in OnMsgNavigate.
1842 is_waiting_for_beforeunload_ack_ = false; 1773 is_waiting_for_beforeunload_ack_ = false;
1843 is_waiting_for_unload_ack_ = false; 1774 is_waiting_for_unload_ack_ = false;
1844 has_timed_out_on_unload_ = false;
1845 } 1775 }
1846 1776
1847 void RenderViewHostImpl::ClearPowerSaveBlockers() { 1777 void RenderViewHostImpl::ClearPowerSaveBlockers() {
1848 STLDeleteValues(&power_save_blockers_); 1778 STLDeleteValues(&power_save_blockers_);
1849 } 1779 }
1850 1780
1851 } // namespace content 1781 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/renderer_host/render_view_host_impl.h ('k') | content/browser/renderer_host/render_widget_helper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698