Chromium Code Reviews| Index: android_webview/browser/aw_browser_terminator.cc |
| diff --git a/android_webview/browser/aw_browser_terminator.cc b/android_webview/browser/aw_browser_terminator.cc |
| index 362d070dc7c91050be096f97d171321be6ea963c..fe7de6b87fe7f460e1601e93879a4a28f8dfae18 100644 |
| --- a/android_webview/browser/aw_browser_terminator.cc |
| +++ b/android_webview/browser/aw_browser_terminator.cc |
| @@ -6,6 +6,7 @@ |
| #include <unistd.h> |
| +#include "android_webview/browser/aw_render_process_gone_delegate.h" |
| #include "android_webview/common/aw_descriptors.h" |
| #include "base/bind.h" |
| #include "base/logging.h" |
| @@ -16,11 +17,64 @@ |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/browser/notification_types.h" |
| #include "content/public/browser/render_process_host.h" |
| +#include "content/public/browser/render_view_host.h" |
| +#include "content/public/browser/render_widget_host.h" |
| +#include "content/public/browser/render_widget_host_iterator.h" |
| +#include "content/public/browser/web_contents.h" |
| using content::BrowserThread; |
| namespace android_webview { |
| +namespace { |
| + |
| +void GetAwRenderProcessGoneDelegatesForRenderProcess( |
| + int render_process_id, |
| + std::vector<AwRenderProcessGoneDelegate*>* delegates) { |
| + content::RenderProcessHost* rph = |
| + content::RenderProcessHost::FromID(render_process_id); |
| + if (!rph) |
| + return; |
| + |
| + std::unique_ptr<content::RenderWidgetHostIterator> widgets( |
| + content::RenderWidgetHost::GetRenderWidgetHosts()); |
| + while (content::RenderWidgetHost* widget = widgets->GetNextHost()) { |
| + content::RenderViewHost* view = content::RenderViewHost::From(widget); |
| + if (view && rph == view->GetProcess()) { |
| + content::WebContents* wc = content::WebContents::FromRenderViewHost(view); |
| + if (wc) { |
| + AwRenderProcessGoneDelegate* delegate = |
| + AwRenderProcessGoneDelegate::FromWebContents(wc); |
| + if (delegate) |
| + delegates->push_back(delegate); |
| + } |
| + } |
| + } |
| +} |
| + |
| +void OnRenderProcessGone(int child_process_id) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + std::vector<AwRenderProcessGoneDelegate*> delegates; |
| + GetAwRenderProcessGoneDelegatesForRenderProcess(child_process_id, &delegates); |
| + for (auto delegate : delegates) |
| + delegate->OnRenderProcessGone(child_process_id); |
| +} |
| + |
| +void OnRenderProcessGoneDetail(int child_process_id, bool crashed) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + std::vector<AwRenderProcessGoneDelegate*> delegates; |
| + GetAwRenderProcessGoneDelegatesForRenderProcess(child_process_id, &delegates); |
| + for (auto delegate : delegates) { |
| + if (!delegate->OnRenderProcessGoneDetail(child_process_id, crashed)) { |
| + // Keeps this log unchanged, CTS test uses it to detect crash. |
| + LOG(FATAL) << "Render process's abnormal termination wasn't handled by" |
|
Tobias Sargeant
2017/01/19 17:28:03
When you rebase, you'll need
crash_reporter::Supp
michaelbai
2017/01/19 17:33:31
Thanks
|
| + << " all associated webviews, triggering application crash"; |
| + } |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| AwBrowserTerminator::AwBrowserTerminator() {} |
| AwBrowserTerminator::~AwBrowserTerminator() {} |
| @@ -42,18 +96,22 @@ void AwBrowserTerminator::OnChildStart(int child_process_id, |
| } |
| void AwBrowserTerminator::ProcessTerminationStatus( |
| + int child_process_id, |
| std::unique_ptr<base::SyncSocket> pipe) { |
| + bool crashed = false; |
| + |
| + // If the child process hasn't written anything into the pipe. This implies |
| + // that it was terminated via SIGKILL by the low memory killer. |
| if (pipe->Peek() >= sizeof(int)) { |
| int exit_code; |
| pipe->Receive(&exit_code, sizeof(exit_code)); |
| - LOG(FATAL) << "Renderer process crash detected (code " << exit_code |
| - << "). Terminating browser."; |
| - } else { |
| - // The child process hasn't written anything into the pipe. This implies |
| - // that it was terminated via SIGKILL by the low memory killer, and thus we |
| - // need to perform a clean exit. |
| - exit(0); |
| + LOG(ERROR) << "Renderer process crash detected (code " << exit_code << ")."; |
| + crashed = true; |
| } |
| + |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&OnRenderProcessGoneDetail, child_process_id, crashed)); |
| } |
| void AwBrowserTerminator::OnChildExit( |
| @@ -77,10 +135,12 @@ void AwBrowserTerminator::OnChildExit( |
| } |
| if (termination_status == base::TERMINATION_STATUS_NORMAL_TERMINATION) |
| return; |
| + OnRenderProcessGone(child_process_id); |
| DCHECK(pipe->handle() != base::SyncSocket::kInvalidHandle); |
| BrowserThread::PostTask( |
| BrowserThread::FILE, FROM_HERE, |
| base::Bind(&AwBrowserTerminator::ProcessTerminationStatus, |
| + child_process_id, |
| base::Passed(std::move(pipe)))); |
| } |