summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorgspencer@chromium.org <gspencer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-14 00:42:23 +0000
committergspencer@chromium.org <gspencer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-14 00:42:23 +0000
commit443b80e00142dab08385eba06fcea79c96bbee6b (patch)
tree157caafda0fc699ff453d0d9666d19f2eeff8869 /chrome/browser
parent458a4362fecfe99bd7bc7e9d918a50fc653b4519 (diff)
downloadchromium_src-443b80e00142dab08385eba06fcea79c96bbee6b.zip
chromium_src-443b80e00142dab08385eba06fcea79c96bbee6b.tar.gz
chromium_src-443b80e00142dab08385eba06fcea79c96bbee6b.tar.bz2
This adds some plumbing for propagating the status and error code of a renderer process that went away so that we can tell at the UI level what happened to the tab: did it crash, or was it killed by the OOM killer (or some other reason). This is in preparation for implementing a new UI for when a process is killed by the OOM on ChromeOS which handles it differently from a crash.
Most of the changes are modifications of the argument list to include a status and error code for the exited process, but in addition the following was done: - Changed the name of DidProcessCrash to GetTerminationStatus. - Added TerminationStatus enum in process_util.h, so it can be used as the status returned by GetTerminationStatus. - Improved process_util_unittest to actually test for crashing and terminated processes on all platforms. - Added a new notification for renderers that were killed. - Added error code information to crash notification. - Added status and error code information to renderer IPC message for RenderViewGone. - Added a UMA histogram count for number of renderer kills. BUG=http://crosbug.com/8505 TEST=ran new unit test. Test passes on try servers. Review URL: http://codereview.chromium.org/5172009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69082 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser_child_process_host.cc32
-rw-r--r--chrome/browser/browser_child_process_host.h22
-rw-r--r--chrome/browser/child_process_launcher.cc23
-rw-r--r--chrome/browser/child_process_launcher.h7
-rw-r--r--chrome/browser/child_process_security_policy_browsertest.cc3
-rw-r--r--chrome/browser/extensions/extension_crash_recovery_browsertest.cc4
-rw-r--r--chrome/browser/extensions/extension_host.cc4
-rw-r--r--chrome/browser/extensions/extension_host.h4
-rw-r--r--chrome/browser/extensions/sandboxed_extension_unpacker.cc2
-rw-r--r--chrome/browser/extensions/sandboxed_extension_unpacker.h2
-rw-r--r--chrome/browser/gpu_process_host.cc4
-rw-r--r--chrome/browser/gpu_process_host.h2
-rw-r--r--chrome/browser/importer/importer.cc2
-rw-r--r--chrome/browser/importer/importer.h2
-rw-r--r--chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc2
-rw-r--r--chrome/browser/in_process_webkit/indexed_db_key_utility_client.h2
-rw-r--r--chrome/browser/metrics/metrics_service.cc8
-rw-r--r--chrome/browser/nacl_host/nacl_process_host.cc7
-rw-r--r--chrome/browser/nacl_host/nacl_process_host.h2
-rw-r--r--chrome/browser/notifications/balloon_host.cc7
-rw-r--r--chrome/browser/notifications/balloon_host.h4
-rw-r--r--chrome/browser/profile_import_process_host.cc5
-rw-r--r--chrome/browser/profile_import_process_host.h4
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc26
-rw-r--r--chrome/browser/renderer_host/render_process_host.h11
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc17
-rw-r--r--chrome/browser/renderer_host/render_view_host.h10
-rw-r--r--chrome/browser/renderer_host/render_view_host_delegate.h5
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc7
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h5
-rw-r--r--chrome/browser/renderer_host/render_widget_host_unittest.cc2
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view.h4
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.cc3
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.h3
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.h3
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm3
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_views.cc6
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_views.h3
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.cc3
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.h3
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.h3
-rw-r--r--chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc3
-rw-r--r--chrome/browser/tab_contents/interstitial_page.cc4
-rw-r--r--chrome/browser/tab_contents/interstitial_page.h5
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc21
-rw-r--r--chrome/browser/tab_contents/tab_contents.h17
-rw-r--r--chrome/browser/tab_contents/web_contents_unittest.cc18
-rw-r--r--chrome/browser/task_manager/task_manager.cc3
-rw-r--r--chrome/browser/utility_process_host.cc4
-rw-r--r--chrome/browser/utility_process_host.h4
-rw-r--r--chrome/browser/web_resource/web_resource_service.cc2
-rw-r--r--chrome/browser/zygote_host_linux.cc32
-rw-r--r--chrome/browser/zygote_host_linux.h24
-rw-r--r--chrome/browser/zygote_main_linux.cc30
54 files changed, 288 insertions, 150 deletions
diff --git a/chrome/browser/browser_child_process_host.cc b/chrome/browser/browser_child_process_host.cc
index 6ad0c44..6b7d47b 100644
--- a/chrome/browser/browser_child_process_host.cc
+++ b/chrome/browser/browser_child_process_host.cc
@@ -141,18 +141,34 @@ void BrowserChildProcessHost::Notify(NotificationType type) {
BrowserThread::UI, FROM_HERE, new ChildNotificationTask(type, this));
}
-bool BrowserChildProcessHost::DidChildCrash() {
- return child_process_->DidProcessCrash();
+base::TerminationStatus BrowserChildProcessHost::GetChildTerminationStatus(
+ int* exit_code) {
+ return child_process_->GetChildTerminationStatus(exit_code);
}
void BrowserChildProcessHost::OnChildDied() {
if (handle() != base::kNullProcessHandle) {
- bool did_crash = DidChildCrash();
- if (did_crash) {
- OnProcessCrashed();
- // Report that this child process crashed.
- Notify(NotificationType::CHILD_PROCESS_CRASHED);
- UMA_HISTOGRAM_COUNTS("ChildProcess.Crashes", this->type());
+ int exit_code;
+ base::TerminationStatus status = GetChildTerminationStatus(&exit_code);
+ switch (status) {
+ case base::TERMINATION_STATUS_PROCESS_CRASHED: {
+ OnProcessCrashed(exit_code);
+
+ // Report that this child process crashed.
+ Notify(NotificationType::CHILD_PROCESS_CRASHED);
+ UMA_HISTOGRAM_COUNTS("ChildProcess.Crashes", this->type());
+ break;
+ }
+ case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: {
+ OnProcessWasKilled(exit_code);
+
+ // Report that this child process was killed.
+ Notify(NotificationType::CHILD_PROCESS_WAS_KILLED);
+ UMA_HISTOGRAM_COUNTS("ChildProcess.Kills", this->type());
+ break;
+ }
+ default:
+ break;
}
// Notify in the main loop of the disconnection.
Notify(NotificationType::CHILD_PROCESS_HOST_DISCONNECTED);
diff --git a/chrome/browser/browser_child_process_host.h b/chrome/browser/browser_child_process_host.h
index f70c035..b7bd39a 100644
--- a/chrome/browser/browser_child_process_host.h
+++ b/chrome/browser/browser_child_process_host.h
@@ -78,12 +78,25 @@ class BrowserChildProcessHost : public ResourceDispatcherHost::Receiver,
base::ProcessHandle GetChildProcessHandle() const;
// ChildProcessLauncher::Client implementation.
- virtual void OnProcessLaunched() { }
+ virtual void OnProcessLaunched() {}
// Derived classes can override this to know if the process crashed.
- virtual void OnProcessCrashed() {}
-
- virtual bool DidChildCrash();
+ // |exit_code| is the status returned when the process crashed (for
+ // posix, as returned from waitpid(), for Windows, as returned from
+ // GetExitCodeProcess()).
+ virtual void OnProcessCrashed(int exit_code) {}
+
+ // Derived classes can override this to know if the process was
+ // killed. |exit_code| is the status returned when the process
+ // was killed (for posix, as returned from waitpid(), for Windows,
+ // as returned from GetExitCodeProcess()).
+ virtual void OnProcessWasKilled(int exit_code) {}
+
+ // Returns the termination status of a child. |exit_code| is the
+ // status returned when the process exited (for posix, as returned
+ // from waitpid(), for Windows, as returned from
+ // GetExitCodeProcess()). |exit_code| may be NULL.
+ virtual base::TerminationStatus GetChildTerminationStatus(int* exit_code);
// Overrides from ChildProcessHost
virtual void OnChildDied();
@@ -111,4 +124,3 @@ class BrowserChildProcessHost : public ResourceDispatcherHost::Receiver,
};
#endif // CHROME_BROWSER_BROWSER_CHILD_PROCESS_HOST_H_
-
diff --git a/chrome/browser/child_process_launcher.cc b/chrome/browser/child_process_launcher.cc
index a4a610a..8ba6941 100644
--- a/chrome/browser/child_process_launcher.cc
+++ b/chrome/browser/child_process_launcher.cc
@@ -311,28 +311,29 @@ base::ProcessHandle ChildProcessLauncher::GetHandle() {
return context_->process_.handle();
}
-bool ChildProcessLauncher::DidProcessCrash() {
- bool did_crash, child_exited;
+base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus(
+ int* exit_code) {
+ base::TerminationStatus status;
base::ProcessHandle handle = context_->process_.handle();
#if defined(OS_LINUX)
if (context_->zygote_) {
- did_crash = ZygoteHost::GetInstance()->DidProcessCrash(handle,
- &child_exited);
+ status = ZygoteHost::GetInstance()->GetTerminationStatus(handle, exit_code);
} else
#endif
{
- did_crash = base::DidProcessCrash(&child_exited, handle);
+ status = base::GetTerminationStatus(handle, exit_code);
}
- // POSIX: If the process crashed, then the kernel closed the socket for it
- // and so the child has already died by the time we get here. Since
- // DidProcessCrash called waitpid with WNOHANG, it'll reap the process.
- // However, if DidProcessCrash didn't reap the child, we'll need to in
+ // POSIX: If the process crashed, then the kernel closed the socket
+ // for it and so the child has already died by the time we get
+ // here. Since GetTerminationStatus called waitpid with WNOHANG,
+ // it'll reap the process. However, if GetTerminationStatus didn't
+ // reap the child (because it was still running), we'll need to
// Terminate via ProcessWatcher. So we can't close the handle here.
- if (child_exited)
+ if (status != base::TERMINATION_STATUS_STILL_RUNNING)
context_->process_.Close();
- return did_crash;
+ return status;
}
void ChildProcessLauncher::SetProcessBackgrounded(bool background) {
diff --git a/chrome/browser/child_process_launcher.h b/chrome/browser/child_process_launcher.h
index 95fb6ea..a3add53 100644
--- a/chrome/browser/child_process_launcher.h
+++ b/chrome/browser/child_process_launcher.h
@@ -50,8 +50,11 @@ class ChildProcessLauncher {
// Getter for the process handle. Only call after the process has started.
base::ProcessHandle GetHandle();
- // Call this when the process exits to know if a process crashed or not.
- bool DidProcessCrash();
+ // Call this when the child process exits to know what happened to
+ // it. |exit_code| is the exit code of the process if it exited
+ // (e.g. status from waitpid if on posix, from GetExitCodeProcess on
+ // Windows). |exit_code| may be NULL.
+ base::TerminationStatus GetChildTerminationStatus(int* exit_code);
// Changes whether the process runs in the background or not. Only call
// this after the process has started.
diff --git a/chrome/browser/child_process_security_policy_browsertest.cc b/chrome/browser/child_process_security_policy_browsertest.cc
index bedac81..4bcd3dc 100644
--- a/chrome/browser/child_process_security_policy_browsertest.cc
+++ b/chrome/browser/child_process_security_policy_browsertest.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
+#include "chrome/common/result_codes.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -43,7 +44,7 @@ IN_PROC_BROWSER_TEST_F(ChildProcessSecurityPolicyInProcessBrowserTest, NoLeak) {
TabContents* tab = browser()->GetTabContentsAt(0);
ASSERT_TRUE(tab != NULL);
base::KillProcess(tab->GetRenderProcessHost()->GetHandle(),
- base::PROCESS_END_KILLED_BY_USER, true);
+ ResultCodes::KILLED, true);
tab->controller().Reload(true);
EXPECT_EQ(
diff --git a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
index 50144e1..1914ec7 100644
--- a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
+++ b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/tab_contents/infobar_delegate.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
+#include "chrome/common/result_codes.h"
#include "chrome/test/ui_test_utils.h"
class ExtensionCrashRecoveryTest : public ExtensionBrowserTest {
@@ -61,8 +62,7 @@ class ExtensionCrashRecoveryTest : public ExtensionBrowserTest {
RenderProcessHost* extension_rph =
extension_host->render_view_host()->process();
- base::KillProcess(extension_rph->GetHandle(),
- base::PROCESS_END_KILLED_BY_USER, false);
+ base::KillProcess(extension_rph->GetHandle(), ResultCodes::KILLED, false);
ASSERT_TRUE(WaitForExtensionCrash(extension_id));
ASSERT_FALSE(
GetExtensionProcessManager()->GetBackgroundHostForExtension(extension));
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index cb6bd6b..1051399 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -288,7 +288,9 @@ void ExtensionHost::ClearInspectorSettings() {
RenderViewHostDelegateHelper::ClearInspectorSettings(profile());
}
-void ExtensionHost::RenderViewGone(RenderViewHost* render_view_host) {
+void ExtensionHost::RenderViewGone(RenderViewHost* render_view_host,
+ base::TerminationStatus status,
+ int error_code) {
// During browser shutdown, we may use sudden termination on an extension
// process, so it is expected to lose our connection to the render view.
// Do nothing.
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index 935b76c..801bdab 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -112,7 +112,9 @@ class ExtensionHost : public RenderViewHostDelegate,
virtual ViewType::Type GetRenderViewType() const;
virtual FileSelect* GetFileSelectDelegate();
virtual int GetBrowserWindowID() const;
- virtual void RenderViewGone(RenderViewHost* render_view_host);
+ virtual void RenderViewGone(RenderViewHost* render_view_host,
+ base::TerminationStatus status,
+ int error_code);
virtual void DidNavigate(RenderViewHost* render_view_host,
const ViewHostMsg_FrameNavigate_Params& params);
virtual void DidStopLoading();
diff --git a/chrome/browser/extensions/sandboxed_extension_unpacker.cc b/chrome/browser/extensions/sandboxed_extension_unpacker.cc
index faf236b..fc01884 100644
--- a/chrome/browser/extensions/sandboxed_extension_unpacker.cc
+++ b/chrome/browser/extensions/sandboxed_extension_unpacker.cc
@@ -181,7 +181,7 @@ void SandboxedExtensionUnpacker::OnUnpackExtensionFailed(
ReportFailure(error);
}
-void SandboxedExtensionUnpacker::OnProcessCrashed() {
+void SandboxedExtensionUnpacker::OnProcessCrashed(int exit_code) {
// Don't report crashes if they happen after we got a response.
if (got_response_)
return;
diff --git a/chrome/browser/extensions/sandboxed_extension_unpacker.h b/chrome/browser/extensions/sandboxed_extension_unpacker.h
index acb4081..e47b26c 100644
--- a/chrome/browser/extensions/sandboxed_extension_unpacker.h
+++ b/chrome/browser/extensions/sandboxed_extension_unpacker.h
@@ -124,7 +124,7 @@ class SandboxedExtensionUnpacker : public UtilityProcessHost::Client {
// SandboxedExtensionUnpacker
virtual void OnUnpackExtensionSucceeded(const DictionaryValue& manifest);
virtual void OnUnpackExtensionFailed(const std::string& error_message);
- virtual void OnProcessCrashed();
+ virtual void OnProcessCrashed(int exit_code);
void ReportFailure(const std::string& message);
void ReportSuccess();
diff --git a/chrome/browser/gpu_process_host.cc b/chrome/browser/gpu_process_host.cc
index af4229a..7ddbdf1 100644
--- a/chrome/browser/gpu_process_host.cc
+++ b/chrome/browser/gpu_process_host.cc
@@ -495,12 +495,12 @@ void GpuProcessHost::OnChildDied() {
BrowserChildProcessHost::OnChildDied();
}
-void GpuProcessHost::OnProcessCrashed() {
+void GpuProcessHost::OnProcessCrashed(int exit_code) {
if (++g_gpu_crash_count >= kGpuMaxCrashCount) {
// The gpu process is too unstable to use. Disable it for current session.
RenderViewHostDelegateHelper::set_gpu_enabled(false);
}
- BrowserChildProcessHost::OnProcessCrashed();
+ BrowserChildProcessHost::OnProcessCrashed(exit_code);
}
bool GpuProcessHost::CanLaunchGpuProcess() const {
diff --git a/chrome/browser/gpu_process_host.h b/chrome/browser/gpu_process_host.h
index a2b3c9e..c60c307 100644
--- a/chrome/browser/gpu_process_host.h
+++ b/chrome/browser/gpu_process_host.h
@@ -113,7 +113,7 @@ class GpuProcessHost : public BrowserChildProcessHost, public NonThreadSafe {
virtual bool CanShutdown();
virtual void OnChildDied();
- virtual void OnProcessCrashed();
+ virtual void OnProcessCrashed(int exit_code);
bool CanLaunchGpuProcess() const;
bool LaunchGpuProcess();
diff --git a/chrome/browser/importer/importer.cc b/chrome/browser/importer/importer.cc
index 861db31..6cf596b 100644
--- a/chrome/browser/importer/importer.cc
+++ b/chrome/browser/importer/importer.cc
@@ -460,7 +460,7 @@ void ExternalProcessImporterClient::NotifyItemFinishedOnIOThread(
profile_import_process_host_->ReportImportItemFinished(import_item);
}
-void ExternalProcessImporterClient::OnProcessCrashed() {
+void ExternalProcessImporterClient::OnProcessCrashed(int exit_code) {
if (cancelled_)
return;
diff --git a/chrome/browser/importer/importer.h b/chrome/browser/importer/importer.h
index 515c58c..bc25850 100644
--- a/chrome/browser/importer/importer.h
+++ b/chrome/browser/importer/importer.h
@@ -344,7 +344,7 @@ class ExternalProcessImporterClient
void NotifyItemFinishedOnIOThread(importer::ImportItem import_item);
// Cancel import on process crash.
- virtual void OnProcessCrashed();
+ virtual void OnProcessCrashed(int exit_code);
// Notifies the importerhost that import has finished, and calls Release().
void Cleanup();
diff --git a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc
index 920da34..e287c2c 100644
--- a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc
+++ b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc
@@ -148,7 +148,7 @@ IndexedDBKeyUtilityClient::Client::Client(IndexedDBKeyUtilityClient* parent)
: parent_(parent) {
}
-void IndexedDBKeyUtilityClient::Client::OnProcessCrashed() {
+void IndexedDBKeyUtilityClient::Client::OnProcessCrashed(int exit_code) {
if (parent_->state_ == STATE_CREATING_KEYS)
parent_->FinishCreatingKeys();
}
diff --git a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h
index ee03ed9..6b8aec1 100644
--- a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h
+++ b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h
@@ -45,7 +45,7 @@ class IndexedDBKeyUtilityClient
explicit Client(IndexedDBKeyUtilityClient* parent);
// UtilityProcessHost::Client
- virtual void OnProcessCrashed();
+ virtual void OnProcessCrashed(int exit_code);
virtual void OnIDBKeysFromValuesAndKeyPathSucceeded(
int id, const std::vector<IndexedDBKey>& keys);
virtual void OnIDBKeysFromValuesAndKeyPathFailed(int id);
diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc
index 092548b..3041549 100644
--- a/chrome/browser/metrics/metrics_service.cc
+++ b/chrome/browser/metrics/metrics_service.cc
@@ -606,11 +606,13 @@ void MetricsService::Observe(NotificationType type,
LogLoadStarted();
break;
- case NotificationType::RENDERER_PROCESS_CLOSED:
- {
+ case NotificationType::RENDERER_PROCESS_CLOSED: {
RenderProcessHost::RendererClosedDetails* process_details =
Details<RenderProcessHost::RendererClosedDetails>(details).ptr();
- if (process_details->did_crash) {
+ if (process_details->status ==
+ base::TERMINATION_STATUS_PROCESS_CRASHED ||
+ process_details->status ==
+ base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
if (process_details->was_extension_renderer) {
LogExtensionRendererCrash();
} else {
diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc
index ded7390..df661e4 100644
--- a/chrome/browser/nacl_host/nacl_process_host.cc
+++ b/chrome/browser/nacl_host/nacl_process_host.cc
@@ -163,10 +163,11 @@ void NaClProcessHost::OnProcessLaunchedByBroker(base::ProcessHandle handle) {
OnProcessLaunched();
}
-bool NaClProcessHost::DidChildCrash() {
+base::TerminationStatus NaClProcessHost::GetChildTerminationStatus(
+ int* exit_code) {
if (running_on_wow64_)
- return base::DidProcessCrash(NULL, handle());
- return BrowserChildProcessHost::DidChildCrash();
+ return base::GetTerminationStatus(handle(), exit_code);
+ return BrowserChildProcessHost::GetChildTerminationStatus(exit_code);
}
void NaClProcessHost::OnChildDied() {
diff --git a/chrome/browser/nacl_host/nacl_process_host.h b/chrome/browser/nacl_host/nacl_process_host.h
index 3b35bf7..5d6cc35 100644
--- a/chrome/browser/nacl_host/nacl_process_host.h
+++ b/chrome/browser/nacl_host/nacl_process_host.h
@@ -37,7 +37,7 @@ class NaClProcessHost : public BrowserChildProcessHost {
void OnProcessLaunchedByBroker(base::ProcessHandle handle);
protected:
- virtual bool DidChildCrash();
+ virtual base::TerminationStatus GetChildTerminationStatus(int* exit_code);
virtual void OnChildDied();
private:
diff --git a/chrome/browser/notifications/balloon_host.cc b/chrome/browser/notifications/balloon_host.cc
index 8c778d0..13b092f 100644
--- a/chrome/browser/notifications/balloon_host.cc
+++ b/chrome/browser/notifications/balloon_host.cc
@@ -91,7 +91,8 @@ const string16& BalloonHost::GetSource() const {
WebPreferences BalloonHost::GetWebkitPrefs() {
WebPreferences web_prefs =
- RenderViewHostDelegateHelper::GetWebkitPrefs(GetProfile(), enable_dom_ui_);
+ RenderViewHostDelegateHelper::GetWebkitPrefs(GetProfile(),
+ enable_dom_ui_);
web_prefs.allow_scripts_to_close_windows = true;
return web_prefs;
}
@@ -132,7 +133,9 @@ void BalloonHost::RenderViewReady(RenderViewHost* render_view_host) {
Source<BalloonHost>(this), NotificationService::NoDetails());
}
-void BalloonHost::RenderViewGone(RenderViewHost* render_view_host) {
+void BalloonHost::RenderViewGone(RenderViewHost* render_view_host,
+ base::TerminationStatus status,
+ int error_code) {
Close(render_view_host);
}
diff --git a/chrome/browser/notifications/balloon_host.h b/chrome/browser/notifications/balloon_host.h
index c5a88e7..c3c058b 100644
--- a/chrome/browser/notifications/balloon_host.h
+++ b/chrome/browser/notifications/balloon_host.h
@@ -49,7 +49,9 @@ class BalloonHost : public RenderViewHostDelegate,
virtual void Close(RenderViewHost* render_view_host);
virtual void RenderViewCreated(RenderViewHost* render_view_host);
virtual void RenderViewReady(RenderViewHost* render_view_host);
- virtual void RenderViewGone(RenderViewHost* render_view_host);
+ virtual void RenderViewGone(RenderViewHost* render_view_host,
+ base::TerminationStatus status,
+ int error_code);
virtual void UpdateTitle(RenderViewHost* render_view_host,
int32 page_id, const std::wstring& title) {}
virtual int GetBrowserWindowID() const;
diff --git a/chrome/browser/profile_import_process_host.cc b/chrome/browser/profile_import_process_host.cc
index 26e4ec1..45ec4f6 100644
--- a/chrome/browser/profile_import_process_host.cc
+++ b/chrome/browser/profile_import_process_host.cc
@@ -127,12 +127,13 @@ void ProfileImportProcessHost::OnMessageReceived(const IPC::Message& message) {
message));
}
-void ProfileImportProcessHost::OnProcessCrashed() {
+void ProfileImportProcessHost::OnProcessCrashed(int exit_code) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserThread::PostTask(
thread_id_, FROM_HERE,
NewRunnableMethod(import_process_client_.get(),
- &ImportProcessClient::OnProcessCrashed));
+ &ImportProcessClient::OnProcessCrashed,
+ exit_code));
}
bool ProfileImportProcessHost::CanShutdown() {
diff --git a/chrome/browser/profile_import_process_host.h b/chrome/browser/profile_import_process_host.h
index a6129a1..fabb947 100644
--- a/chrome/browser/profile_import_process_host.h
+++ b/chrome/browser/profile_import_process_host.h
@@ -40,7 +40,7 @@ class ProfileImportProcessHost : public BrowserChildProcessHost {
// These methods are used by the ProfileImportProcessHost to pass messages
// received from the external process back to the ImportProcessClient in
// ImporterHost.
- virtual void OnProcessCrashed() {}
+ virtual void OnProcessCrashed(int exit_status) {}
virtual void OnImportStart() {}
virtual void OnImportFinished(bool succeeded, std::string error_msg) {}
virtual void OnImportItemStart(int item) {}
@@ -126,7 +126,7 @@ class ProfileImportProcessHost : public BrowserChildProcessHost {
virtual void OnMessageReceived(const IPC::Message& message);
// Overridden from BrowserChildProcessHost:
- virtual void OnProcessCrashed();
+ virtual void OnProcessCrashed(int exit_code);
virtual bool CanShutdown();
virtual URLRequestContext* GetRequestContext(
uint32 request_id,
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index 98b642b..e2c8780 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -989,16 +989,26 @@ void BrowserRenderProcessHost::OnChannelError() {
if (!channel_.get())
return;
- // NULL in single process mode or if fast termination happened.
- bool did_crash =
- child_process_.get() ? child_process_->DidProcessCrash() : false;
-
- if (did_crash) {
+ // child_process_ can be NULL in single process mode or if fast
+ // termination happened.
+ int exit_code = 0;
+ base::TerminationStatus status =
+ child_process_.get() ?
+ child_process_->GetChildTerminationStatus(&exit_code) :
+ base::TERMINATION_STATUS_NORMAL_TERMINATION;
+
+ if (status == base::TERMINATION_STATUS_PROCESS_CRASHED ||
+ status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildCrashes",
extension_process_ ? 2 : 1);
}
- RendererClosedDetails details(did_crash, extension_process_);
+ if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
+ UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildKills",
+ extension_process_ ? 2 : 1);
+ }
+
+ RendererClosedDetails details(status, exit_code, extension_process_);
NotificationService::current()->Notify(
NotificationType::RENDERER_PROCESS_CLOSED,
Source<RenderProcessHost>(this),
@@ -1011,7 +1021,9 @@ void BrowserRenderProcessHost::OnChannelError() {
IDMap<IPC::Channel::Listener>::iterator iter(&listeners_);
while (!iter.IsAtEnd()) {
iter.GetCurrentValue()->OnMessageReceived(
- ViewHostMsg_RenderViewGone(iter.GetCurrentKey()));
+ ViewHostMsg_RenderViewGone(iter.GetCurrentKey(),
+ static_cast<int>(status),
+ exit_code));
iter.Advance();
}
diff --git a/chrome/browser/renderer_host/render_process_host.h b/chrome/browser/renderer_host/render_process_host.h
index a5fd378..c9a8abc 100644
--- a/chrome/browser/renderer_host/render_process_host.h
+++ b/chrome/browser/renderer_host/render_process_host.h
@@ -11,6 +11,7 @@
#include "app/surface/transport_dib.h"
#include "base/id_map.h"
#include "base/process.h"
+#include "base/process_util.h"
#include "base/scoped_ptr.h"
#include "base/time.h"
#include "chrome/common/visitedlink_common.h"
@@ -48,11 +49,15 @@ class RenderProcessHost : public IPC::Channel::Sender,
// Details for RENDERER_PROCESS_CLOSED notifications.
struct RendererClosedDetails {
- RendererClosedDetails(bool did_crash, bool was_extension_renderer) {
- this->did_crash = did_crash;
+ RendererClosedDetails(base::TerminationStatus status,
+ int exit_code,
+ bool was_extension_renderer) {
+ this->status = status;
+ this->exit_code = exit_code;
this->was_extension_renderer = was_extension_renderer;
}
- bool did_crash;
+ base::TerminationStatus status;
+ int exit_code;
bool was_extension_renderer;
};
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 1b1cf0b..dc358b6 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -140,7 +140,8 @@ RenderViewHost::RenderViewHost(SiteInstance* instance,
session_storage_namespace_(session_storage),
is_extension_process_(false),
autofill_query_id_(0),
- save_accessibility_tree_for_testing_(false) {
+ save_accessibility_tree_for_testing_(false),
+ render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING) {
if (!session_storage_namespace_) {
session_storage_namespace_ =
new SessionStorageNamespace(process()->profile());
@@ -998,15 +999,23 @@ void RenderViewHost::OnMsgRunModal(IPC::Message* reply_msg) {
}
void RenderViewHost::OnMsgRenderViewReady() {
+ render_view_termination_status_ = base::TERMINATION_STATUS_STILL_RUNNING;
WasResized();
delegate_->RenderViewReady(this);
}
-void RenderViewHost::OnMsgRenderViewGone() {
+void RenderViewHost::OnMsgRenderViewGone(int status, int exit_code) {
+ // Keep the termination status so we can get at it later when we
+ // need to know why it died.
+ render_view_termination_status_ =
+ static_cast<base::TerminationStatus>(status);
+
// Our base class RenderWidgetHost needs to reset some stuff.
- RendererExited();
+ RendererExited(render_view_termination_status_, exit_code);
- delegate_->RenderViewGone(this);
+ delegate_->RenderViewGone(this,
+ static_cast<base::TerminationStatus>(status),
+ exit_code);
}
// Called when the renderer navigates. For every frame loaded, we'll get this
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index b5399bf..81223ea 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "base/process_util.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "chrome/browser/ui/find_bar/find_bar_controller.h"
@@ -127,6 +128,10 @@ class RenderViewHost : public RenderWidgetHost {
// because it is overridden by TestRenderViewHost.
virtual bool IsRenderViewLive() const;
+ base::TerminationStatus render_view_termination_status() const {
+ return render_view_termination_status_;
+ }
+
// Send the renderer process the current preferences supplied by the
// RenderViewHostDelegate.
void SyncRendererPrefs();
@@ -550,7 +555,7 @@ class RenderViewHost : public RenderWidgetHost {
void OnMsgShowFullscreenWidget(int route_id);
void OnMsgRunModal(IPC::Message* reply_msg);
void OnMsgRenderViewReady();
- void OnMsgRenderViewGone();
+ void OnMsgRenderViewGone(int status, int error_code);
void OnMsgNavigate(const IPC::Message& msg);
void OnMsgUpdateState(int32 page_id,
const std::string& state);
@@ -819,6 +824,9 @@ class RenderViewHost : public RenderWidgetHost {
// The most recently received accessibility tree - for unit testing only.
webkit_glue::WebAccessibility accessibility_tree_;
+ // The termination status of the last render view that terminated.
+ base::TerminationStatus render_view_termination_status_;
+
DISALLOW_COPY_AND_ASSIGN(RenderViewHost);
};
diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h
index a566062..89f7d94 100644
--- a/chrome/browser/renderer_host/render_view_host_delegate.h
+++ b/chrome/browser/renderer_host/render_view_host_delegate.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/process_util.h"
#include "base/ref_counted.h"
#include "base/string16.h"
#include "chrome/common/content_settings_types.h"
@@ -711,7 +712,9 @@ class RenderViewHostDelegate {
virtual void RenderViewReady(RenderViewHost* render_view_host) {}
// The RenderView died somehow (crashed or was killed by the user).
- virtual void RenderViewGone(RenderViewHost* render_view_host) {}
+ virtual void RenderViewGone(RenderViewHost* render_view_host,
+ base::TerminationStatus status,
+ int error_code) {}
// The RenderView is going to be deleted. This is called when each
// RenderView is going to be destroyed
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index 3fa5610..3c71440b 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -643,7 +643,8 @@ void RenderWidgetHost::ForwardTouchEvent(
}
#endif
-void RenderWidgetHost::RendererExited() {
+void RenderWidgetHost::RendererExited(base::TerminationStatus status,
+ int exit_code) {
// Clearing this flag causes us to re-create the renderer when recovering
// from a crashed renderer.
renderer_initialized_ = false;
@@ -671,7 +672,7 @@ void RenderWidgetHost::RendererExited() {
is_accelerated_compositing_active_ = false;
if (view_) {
- view_->RenderViewGone();
+ view_->RenderViewGone(status, exit_code);
view_ = NULL; // The View should be deleted by RenderViewGone.
}
@@ -777,7 +778,7 @@ void RenderWidgetHost::OnMsgRenderViewReady() {
WasResized();
}
-void RenderWidgetHost::OnMsgRenderViewGone() {
+void RenderWidgetHost::OnMsgRenderViewGone(int status, int exit_code) {
// TODO(evanm): This synchronously ends up calling "delete this".
// Is that really what we want in response to this message? I'm matching
// previous behavior of the code here.
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index b0192a4..90204aa 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -12,6 +12,7 @@
#include "app/surface/transport_dib.h"
#include "base/gtest_prod_util.h"
+#include "base/process_util.h"
#include "base/scoped_ptr.h"
#include "base/string16.h"
#include "base/timer.h"
@@ -415,7 +416,7 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// Called when we receive a notification indicating that the renderer
// process has gone. This will reset our state so that our state will be
// consistent if a new renderer is created.
- void RendererExited();
+ void RendererExited(base::TerminationStatus status, int exit_code);
// Retrieves an id the renderer can use to refer to its view.
// This is used for various IPC messages, including plugins.
@@ -473,7 +474,7 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// IPC message handlers
void OnMsgRenderViewReady();
- void OnMsgRenderViewGone();
+ void OnMsgRenderViewGone(int status, int error_code);
void OnMsgClose();
void OnMsgRequestMove(const gfx::Rect& pos);
void OnMsgPaintAtSizeAck(int tag, const gfx::Size& size);
diff --git a/chrome/browser/renderer_host/render_widget_host_unittest.cc b/chrome/browser/renderer_host/render_widget_host_unittest.cc
index 72495d3..758a5bd 100644
--- a/chrome/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chrome/browser/renderer_host/render_widget_host_unittest.cc
@@ -397,7 +397,7 @@ TEST_F(RenderWidgetHostTest, ResizeThenCrash) {
// resize ack logic is cleared. Must clear the view first so it doesn't get
// deleted.
host_->set_view(NULL);
- host_->RendererExited();
+ host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
EXPECT_FALSE(host_->resize_ack_pending_);
EXPECT_EQ(gfx::Size(), host_->in_flight_size_);
diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h
index af6300e..14cf129 100644
--- a/chrome/browser/renderer_host/render_widget_host_view.h
+++ b/chrome/browser/renderer_host/render_widget_host_view.h
@@ -14,6 +14,7 @@
#include <vector>
#include "app/surface/transport_dib.h"
+#include "base/process_util.h"
#include "gfx/native_widget_types.h"
#include "gfx/rect.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -152,7 +153,8 @@ class RenderWidgetHostView {
const std::vector<gfx::Rect>& copy_rects) = 0;
// Notifies the View that the renderer has ceased to exist.
- virtual void RenderViewGone() = 0;
+ virtual void RenderViewGone(base::TerminationStatus status,
+ int error_code) = 0;
// Notifies the View that the renderer will be delete soon.
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) = 0;
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
index 78b26e2..cf3418a 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -681,7 +681,8 @@ void RenderWidgetHostViewGtk::DidUpdateBackingStore(
}
}
-void RenderWidgetHostViewGtk::RenderViewGone() {
+void RenderWidgetHostViewGtk::RenderViewGone(base::TerminationStatus status,
+ int error_code) {
Destroy();
plugin_container_manager_.set_host_widget(NULL);
}
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.h b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
index cd89ddb..7af66f8 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
@@ -77,7 +77,8 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView,
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
const std::vector<gfx::Rect>& copy_rects);
- virtual void RenderViewGone();
+ virtual void RenderViewGone(base::TerminationStatus status,
+ int error_code);
virtual void Destroy();
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {}
virtual void SetTooltipText(const std::wstring& tooltip_text);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h
index f4dfd25..46efeee 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h
@@ -200,7 +200,8 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView {
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
const std::vector<gfx::Rect>& copy_rects);
- virtual void RenderViewGone();
+ virtual void RenderViewGone(base::TerminationStatus status,
+ int error_code);
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {};
virtual void Destroy();
virtual void SetTooltipText(const std::wstring& tooltip_text);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index f88025e..842bf9a 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -794,7 +794,8 @@ void RenderWidgetHostViewMac::DidUpdateBackingStore(
HandleDelayedGpuViewHiding();
}
-void RenderWidgetHostViewMac::RenderViewGone() {
+void RenderWidgetHostViewMac::RenderViewGone(base::TerminationStatus status,
+ int error_code) {
// TODO(darin): keep this around, and draw sad-tab into it.
UpdateCursorIfOverSelf();
Destroy();
diff --git a/chrome/browser/renderer_host/render_widget_host_view_views.cc b/chrome/browser/renderer_host/render_widget_host_view_views.cc
index cdc2e38..ea808f0 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_views.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_views.cc
@@ -131,7 +131,8 @@ RenderWidgetHostViewViews::RenderWidgetHostViewViews(RenderWidgetHost* host)
}
RenderWidgetHostViewViews::~RenderWidgetHostViewViews() {
- RenderViewGone();
+ RenderViewGone(base::TERMINATION_STATUS_NORMAL_TERMINATION,
+ ResultCodes::NORMAL_EXIT);
}
void RenderWidgetHostViewViews::InitAsChild() {
@@ -286,7 +287,8 @@ void RenderWidgetHostViewViews::DidUpdateBackingStore(
}
}
-void RenderWidgetHostViewViews::RenderViewGone() {
+void RenderWidgetHostViewViews::RenderViewGone(base::TerminationStatus status,
+ int error_code) {
GetRenderWidgetHost()->ViewDestroyed();
Destroy();
}
diff --git a/chrome/browser/renderer_host/render_widget_host_view_views.h b/chrome/browser/renderer_host/render_widget_host_view_views.h
index a9a918f..9c5c8cb 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_views.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_views.h
@@ -60,7 +60,8 @@ class RenderWidgetHostViewViews : public RenderWidgetHostView,
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
const std::vector<gfx::Rect>& copy_rects);
- virtual void RenderViewGone();
+ virtual void RenderViewGone(base::TerminationStatus status,
+ int error_code);
virtual void Destroy();
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {}
virtual void SetTooltipText(const std::wstring& tooltip_text);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc
index a665794..f5afe70 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc
@@ -722,7 +722,8 @@ void RenderWidgetHostViewWin::DidUpdateBackingStore(
Redraw();
}
-void RenderWidgetHostViewWin::RenderViewGone() {
+void RenderWidgetHostViewWin::RenderViewGone(base::TerminationStatus status,
+ int error_code) {
// TODO(darin): keep this around, and draw sad-tab into it.
UpdateCursorIfOverSelf();
being_destroyed_ = true;
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h
index 282dfe9..1f67814 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.h
@@ -148,7 +148,8 @@ class RenderWidgetHostViewWin
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
const std::vector<gfx::Rect>& copy_rects);
- virtual void RenderViewGone();
+ virtual void RenderViewGone(base::TerminationStatus status,
+ int error_code);
virtual void WillWmDestroy(); // called by TabContents before DestroyWindow
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh);
virtual void Destroy();
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.h b/chrome/browser/renderer_host/test/test_render_view_host.h
index a2ff8f7..7aa9638 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.h
+++ b/chrome/browser/renderer_host/test/test_render_view_host.h
@@ -83,7 +83,8 @@ class TestRenderWidgetHostView : public RenderWidgetHostView {
virtual void DidUpdateBackingStore(
const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
const std::vector<gfx::Rect>& rects) {}
- virtual void RenderViewGone() { delete this; }
+ virtual void RenderViewGone(base::TerminationStatus status,
+ int error_code) { delete this; }
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) { }
virtual void Destroy() {}
virtual void PrepareToDestroy() {}
diff --git a/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc b/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc
index 06ce085..3681c70 100644
--- a/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc
+++ b/chrome/browser/renderer_host/test/web_cache_manager_browsertest.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/renderer_host/web_cache_manager.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
+#include "chrome/common/result_codes.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -33,7 +34,7 @@ IN_PROC_BROWSER_TEST_F(WebCacheManagerBrowserTest, FLAKY_CrashOnceOnly) {
TabContents* tab = browser()->GetTabContentsAt(0);
ASSERT_TRUE(tab != NULL);
base::KillProcess(tab->GetRenderProcessHost()->GetHandle(),
- base::PROCESS_END_KILLED_BY_USER, true);
+ ResultCodes::KILLED, true);
browser()->SelectTabContentsAt(0, true);
browser()->NewTab();
diff --git a/chrome/browser/tab_contents/interstitial_page.cc b/chrome/browser/tab_contents/interstitial_page.cc
index d3c0429..bc9920b 100644
--- a/chrome/browser/tab_contents/interstitial_page.cc
+++ b/chrome/browser/tab_contents/interstitial_page.cc
@@ -333,7 +333,9 @@ const GURL& InterstitialPage::GetURL() const {
return url_;
}
-void InterstitialPage::RenderViewGone(RenderViewHost* render_view_host) {
+void InterstitialPage::RenderViewGone(RenderViewHost* render_view_host,
+ base::TerminationStatus status,
+ int error_code) {
// Our renderer died. This should not happen in normal cases.
// Just dismiss the interstitial.
DontProceed();
diff --git a/chrome/browser/tab_contents/interstitial_page.h b/chrome/browser/tab_contents/interstitial_page.h
index 50ede04..2faad77 100644
--- a/chrome/browser/tab_contents/interstitial_page.h
+++ b/chrome/browser/tab_contents/interstitial_page.h
@@ -9,6 +9,7 @@
#include <map>
#include <string>
+#include "base/process_util.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/renderer_host/render_view_host_delegate.h"
#include "chrome/common/notification_observer.h"
@@ -124,7 +125,9 @@ class InterstitialPage : public NotificationObserver,
// RenderViewHostDelegate implementation:
virtual View* GetViewDelegate();
virtual const GURL& GetURL() const;
- virtual void RenderViewGone(RenderViewHost* render_view_host);
+ virtual void RenderViewGone(RenderViewHost* render_view_host,
+ base::TerminationStatus status,
+ int error_code);
virtual void DidNavigate(RenderViewHost* render_view_host,
const ViewHostMsg_FrameNavigate_Params& params);
virtual void UpdateTitle(RenderViewHost* render_view_host,
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index 34ec892..f95634f 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -336,7 +336,8 @@ TabContents::TabContents(Profile* profile,
bookmark_drag_(NULL),
ALLOW_THIS_IN_INITIALIZER_LIST(fav_icon_helper_(this)),
is_loading_(false),
- is_crashed_(false),
+ crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
+ crashed_error_code_(0),
waiting_for_response_(false),
max_page_id_(-1),
current_load_start_(),
@@ -767,11 +768,12 @@ void TabContents::RemoveNavigationObserver(WebNavigationObserver* observer) {
web_navigation_observers_.RemoveObserver(observer);
}
-void TabContents::SetIsCrashed(bool state) {
- if (state == is_crashed_)
+void TabContents::SetIsCrashed(base::TerminationStatus status, int error_code) {
+ if (status == crashed_status_)
return;
- is_crashed_ = state;
+ crashed_status_ = status;
+ crashed_error_code_ = error_code;
NotifyNavigationStateChanged(INVALIDATE_TAB);
}
@@ -2423,7 +2425,7 @@ void TabContents::RenderViewReady(RenderViewHost* rvh) {
NotifyConnected();
bool was_crashed = is_crashed();
- SetIsCrashed(false);
+ SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0);
// Restore the focus to the tab (otherwise the focus will be on the top
// window).
@@ -2433,7 +2435,9 @@ void TabContents::RenderViewReady(RenderViewHost* rvh) {
}
}
-void TabContents::RenderViewGone(RenderViewHost* rvh) {
+void TabContents::RenderViewGone(RenderViewHost* rvh,
+ base::TerminationStatus status,
+ int error_code) {
// Ask the print preview if this renderer was valuable.
if (!printing_->OnRenderViewGone(rvh))
return;
@@ -2444,7 +2448,7 @@ void TabContents::RenderViewGone(RenderViewHost* rvh) {
SetIsLoading(false, NULL);
NotifyDisconnected();
- SetIsCrashed(true);
+ SetIsCrashed(status, error_code);
// Remove all infobars.
for (int i = infobar_delegate_count() - 1; i >=0 ; --i)
@@ -3087,7 +3091,8 @@ void TabContents::DidStartLoadingFromRenderManager(
void TabContents::RenderViewGoneFromRenderManager(
RenderViewHost* render_view_host) {
- RenderViewGone(render_view_host);
+ DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING);
+ RenderViewGone(render_view_host, crashed_status_, crashed_error_code_);
}
void TabContents::UpdateRenderViewSizeForRenderManager() {
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index 122380a..7800ee9 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -308,8 +308,14 @@ class TabContents : public PageNavigator,
// Indicates whether this tab should be considered crashed. The setter will
// also notify the delegate when the flag is changed.
- bool is_crashed() const { return is_crashed_; }
- void SetIsCrashed(bool state);
+ bool is_crashed() const {
+ return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED ||
+ crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
+ crashed_status_ == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
+ }
+ base::TerminationStatus crashed_status() const { return crashed_status_; }
+ int crashed_error_code() const { return crashed_error_code_; }
+ void SetIsCrashed(base::TerminationStatus status, int error_code);
// Call this after updating a page action to notify clients about the changes.
void PageActionStateChanged();
@@ -958,7 +964,9 @@ class TabContents : public PageNavigator,
virtual int GetBrowserWindowID() const;
virtual void RenderViewCreated(RenderViewHost* render_view_host);
virtual void RenderViewReady(RenderViewHost* render_view_host);
- virtual void RenderViewGone(RenderViewHost* render_view_host);
+ virtual void RenderViewGone(RenderViewHost* render_view_host,
+ base::TerminationStatus status,
+ int error_code);
virtual void RenderViewDeleted(RenderViewHost* render_view_host);
virtual void DidNavigate(RenderViewHost* render_view_host,
const ViewHostMsg_FrameNavigate_Params& params);
@@ -1146,7 +1154,8 @@ class TabContents : public PageNavigator,
bool is_loading_;
// Indicates if the tab is considered crashed.
- bool is_crashed_;
+ base::TerminationStatus crashed_status_;
+ int crashed_error_code_;
// See waiting_for_response() above.
bool waiting_for_response_;
diff --git a/chrome/browser/tab_contents/web_contents_unittest.cc b/chrome/browser/tab_contents/web_contents_unittest.cc
index abb1578..67d93a3 100644
--- a/chrome/browser/tab_contents/web_contents_unittest.cc
+++ b/chrome/browser/tab_contents/web_contents_unittest.cc
@@ -120,8 +120,8 @@ class TestInterstitialPage : public InterstitialPage {
DidNavigate(render_view_host(), params);
}
- void TestRenderViewGone() {
- RenderViewGone(render_view_host());
+ void TestRenderViewGone(base::TerminationStatus status, int error_code) {
+ RenderViewGone(render_view_host(), status, error_code);
}
bool is_showing() const {
@@ -1151,7 +1151,9 @@ TEST_F(TabContentsTest, ShowInterstitialCrashRendererThenGoBack) {
interstitial->TestDidNavigate(2, interstitial_url);
// Crash the renderer
- rvh()->TestOnMessageReceived(ViewHostMsg_RenderViewGone(0));
+ rvh()->TestOnMessageReceived(
+ ViewHostMsg_RenderViewGone(
+ 0, base::TERMINATION_STATUS_PROCESS_CRASHED, -1));
// While the interstitial is showing, go back.
controller().GoBack();
@@ -1186,7 +1188,9 @@ TEST_F(TabContentsTest, ShowInterstitialCrashRendererThenNavigate) {
interstitial->Show();
// Crash the renderer
- rvh()->TestOnMessageReceived(ViewHostMsg_RenderViewGone(0));
+ rvh()->TestOnMessageReceived(
+ ViewHostMsg_RenderViewGone(
+ 0, base::TERMINATION_STATUS_PROCESS_CRASHED, -1));
interstitial->TestDidNavigate(2, interstitial_url);
}
@@ -1429,7 +1433,8 @@ TEST_F(TabContentsTest, InterstitialCrasher) {
TestInterstitialPageStateGuard state_guard(interstitial);
interstitial->Show();
// Simulate a renderer crash before the interstitial is shown.
- interstitial->TestRenderViewGone();
+ interstitial->TestRenderViewGone(
+ base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
// The interstitial should have been dismissed.
EXPECT_TRUE(deleted);
EXPECT_EQ(TestInterstitialPage::CANCELED, state);
@@ -1440,7 +1445,8 @@ TEST_F(TabContentsTest, InterstitialCrasher) {
interstitial->Show();
interstitial->TestDidNavigate(1, url);
// Simulate a renderer crash.
- interstitial->TestRenderViewGone();
+ interstitial->TestRenderViewGone(
+ base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
// The interstitial should have been dismissed.
EXPECT_TRUE(deleted);
EXPECT_EQ(TestInterstitialPage::CANCELED, state);
diff --git a/chrome/browser/task_manager/task_manager.cc b/chrome/browser/task_manager/task_manager.cc
index 2dc5029..da19fda 100644
--- a/chrome/browser/task_manager/task_manager.cc
+++ b/chrome/browser/task_manager/task_manager.cc
@@ -26,6 +26,7 @@
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/task_manager/task_manager_resource_providers.h"
#include "chrome/common/pref_names.h"
+#include "chrome/common/result_codes.h"
#include "chrome/common/url_constants.h"
#include "grit/app_resources.h"
#include "grit/chromium_strings.h"
@@ -944,7 +945,7 @@ void TaskManager::KillProcess(int index) {
base::ProcessHandle process = model_->GetResourceProcessHandle(index);
DCHECK(process);
if (process != base::GetCurrentProcessHandle())
- base::KillProcess(process, base::PROCESS_END_KILLED_BY_USER, false);
+ base::KillProcess(process, ResultCodes::KILLED, false);
}
void TaskManager::ActivateProcess(int index) {
diff --git a/chrome/browser/utility_process_host.cc b/chrome/browser/utility_process_host.cc
index 1756d3e..b8d6a77 100644
--- a/chrome/browser/utility_process_host.cc
+++ b/chrome/browser/utility_process_host.cc
@@ -159,10 +159,10 @@ void UtilityProcessHost::OnMessageReceived(const IPC::Message& message) {
NewRunnableMethod(client_.get(), &Client::OnMessageReceived, message));
}
-void UtilityProcessHost::OnProcessCrashed() {
+void UtilityProcessHost::OnProcessCrashed(int exit_code) {
BrowserThread::PostTask(
client_thread_id_, FROM_HERE,
- NewRunnableMethod(client_.get(), &Client::OnProcessCrashed));
+ NewRunnableMethod(client_.get(), &Client::OnProcessCrashed, exit_code));
}
bool UtilityProcessHost::CanShutdown() {
diff --git a/chrome/browser/utility_process_host.h b/chrome/browser/utility_process_host.h
index 559f39e..96879a8 100644
--- a/chrome/browser/utility_process_host.h
+++ b/chrome/browser/utility_process_host.h
@@ -39,7 +39,7 @@ class UtilityProcessHost : public BrowserChildProcessHost {
Client() {}
// Called when the process has crashed.
- virtual void OnProcessCrashed() {}
+ virtual void OnProcessCrashed(int exit_code) {}
// Called when the extension has unpacked successfully. |manifest| is the
// parsed manifest.json file. |catalogs| contains list of all parsed
@@ -153,7 +153,7 @@ class UtilityProcessHost : public BrowserChildProcessHost {
virtual void OnMessageReceived(const IPC::Message& message);
// BrowserChildProcessHost:
- virtual void OnProcessCrashed();
+ virtual void OnProcessCrashed(int exit_code);
virtual bool CanShutdown();
virtual URLRequestContext* GetRequestContext(
uint32 request_id,
diff --git a/chrome/browser/web_resource/web_resource_service.cc b/chrome/browser/web_resource/web_resource_service.cc
index ab557f5..e1de48a 100644
--- a/chrome/browser/web_resource/web_resource_service.cc
+++ b/chrome/browser/web_resource/web_resource_service.cc
@@ -157,7 +157,7 @@ class WebResourceService::UnpackerClient
~UnpackerClient() {}
// UtilityProcessHost::Client
- virtual void OnProcessCrashed() {
+ virtual void OnProcessCrashed(int exit_code) {
if (got_response_)
return;
diff --git a/chrome/browser/zygote_host_linux.cc b/chrome/browser/zygote_host_linux.cc
index 74b6852..e4e7ce3 100644
--- a/chrome/browser/zygote_host_linux.cc
+++ b/chrome/browser/zygote_host_linux.cc
@@ -27,6 +27,7 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/process_watcher.h"
+#include "chrome/common/result_codes.h"
#include "sandbox/linux/suid/suid_unsafe_environment_variables.h"
@@ -316,13 +317,18 @@ void ZygoteHost::EnsureProcessTerminated(pid_t process) {
PLOG(ERROR) << "write";
}
-bool ZygoteHost::DidProcessCrash(base::ProcessHandle handle,
- bool* child_exited) {
+base::TerminationStatus ZygoteHost::GetTerminationStatus(
+ base::ProcessHandle handle,
+ int* exit_code) {
DCHECK(init_);
Pickle pickle;
- pickle.WriteInt(kCmdDidProcessCrash);
+ pickle.WriteInt(kCmdGetTerminationStatus);
pickle.WriteInt(handle);
+ // Set this now to handle the early termination cases.
+ if (exit_code)
+ *exit_code = ResultCodes::NORMAL_EXIT;
+
static const unsigned kMaxMessageLength = 128;
char buf[kMaxMessageLength];
ssize_t len;
@@ -336,23 +342,23 @@ bool ZygoteHost::DidProcessCrash(base::ProcessHandle handle,
if (len == -1) {
LOG(WARNING) << "Error reading message from zygote: " << errno;
- return false;
+ return base::TERMINATION_STATUS_NORMAL_TERMINATION;
} else if (len == 0) {
LOG(WARNING) << "Socket closed prematurely.";
- return false;
+ return base::TERMINATION_STATUS_NORMAL_TERMINATION;
}
Pickle read_pickle(buf, len);
- bool did_crash, tmp_child_exited;
+ int status, tmp_exit_code;
void* iter = NULL;
- if (!read_pickle.ReadBool(&iter, &did_crash) ||
- !read_pickle.ReadBool(&iter, &tmp_child_exited)) {
- LOG(WARNING) << "Error parsing DidProcessCrash response from zygote.";
- return false;
+ if (!read_pickle.ReadInt(&iter, &status) ||
+ !read_pickle.ReadInt(&iter, &tmp_exit_code)) {
+ LOG(WARNING) << "Error parsing GetTerminationStatus response from zygote.";
+ return base::TERMINATION_STATUS_NORMAL_TERMINATION;
}
- if (child_exited)
- *child_exited = tmp_child_exited;
+ if (exit_code)
+ *exit_code = tmp_exit_code;
- return did_crash;
+ return static_cast<base::TerminationStatus>(status);
}
diff --git a/chrome/browser/zygote_host_linux.h b/chrome/browser/zygote_host_linux.h
index 01a6443..e13f1b4 100644
--- a/chrome/browser/zygote_host_linux.h
+++ b/chrome/browser/zygote_host_linux.h
@@ -14,6 +14,7 @@
#include "base/global_descriptors_posix.h"
#include "base/lock.h"
#include "base/process.h"
+#include "base/process_util.h"
template<typename Type>
struct DefaultSingletonTraits;
@@ -37,26 +38,27 @@ class ZygoteHost {
const base::GlobalDescriptors::Mapping& mapping);
void EnsureProcessTerminated(pid_t process);
- // Get the termination status (exit code) of the process and return true if
- // the status indicates the process crashed. |child_exited| is set to true
- // iff the child process has terminated. (|child_exited| may be NULL.)
- bool DidProcessCrash(base::ProcessHandle handle, bool* child_exited);
+ // Get the termination status (and, optionally, the exit code) of
+ // the process. |exit_code| is set to the exit code of the child
+ // process. (|exit_code| may be NULL.)
+ base::TerminationStatus GetTerminationStatus(base::ProcessHandle handle,
+ int* exit_code);
// These are the command codes used on the wire between the browser and the
// zygote.
enum {
- kCmdFork = 0, // Fork off a new renderer.
- kCmdReap = 1, // Reap a renderer child.
- kCmdDidProcessCrash = 2, // Check if child process crashed.
- kCmdGetSandboxStatus = 3, // Read a bitmask of kSandbox*
+ kCmdFork = 0, // Fork off a new renderer.
+ kCmdReap = 1, // Reap a renderer child.
+ kCmdGetTerminationStatus = 2, // Check what happend to a child process.
+ kCmdGetSandboxStatus = 3, // Read a bitmask of kSandbox*
};
// These form a bitmask which describes the conditions of the sandbox that
// the zygote finds itself in.
enum {
- kSandboxSUID = 1 << 0, // SUID sandbox active
- kSandboxPIDNS = 1 << 1, // SUID sandbox is using the PID namespace
- kSandboxNetNS = 1 << 2, // SUID sandbox is using the network namespace
+ kSandboxSUID = 1 << 0, // SUID sandbox active
+ kSandboxPIDNS = 1 << 1, // SUID sandbox is using the PID namespace
+ kSandboxNetNS = 1 << 2, // SUID sandbox is using the network namespace
kSandboxSeccomp = 1 << 3, // seccomp sandbox active.
};
diff --git a/chrome/browser/zygote_main_linux.cc b/chrome/browser/zygote_main_linux.cc
index 5943d11..1b26a6b 100644
--- a/chrome/browser/zygote_main_linux.cc
+++ b/chrome/browser/zygote_main_linux.cc
@@ -41,6 +41,7 @@
#include "chrome/common/main_function_params.h"
#include "chrome/common/pepper_plugin_registry.h"
#include "chrome/common/process_watcher.h"
+#include "chrome/common/result_codes.h"
#include "chrome/common/sandbox_methods_linux.h"
#include "media/base/media.h"
@@ -167,10 +168,10 @@ class Zygote {
break;
HandleReapRequest(fd, pickle, iter);
return false;
- case ZygoteHost::kCmdDidProcessCrash:
+ case ZygoteHost::kCmdGetTerminationStatus:
if (!fds.empty())
break;
- HandleDidProcessCrash(fd, pickle, iter);
+ HandleGetTerminationStatus(fd, pickle, iter);
return false;
case ZygoteHost::kCmdGetSandboxStatus:
HandleGetSandboxStatus(fd, pickle, iter);
@@ -209,26 +210,31 @@ class Zygote {
ProcessWatcher::EnsureProcessTerminated(actual_child);
}
- void HandleDidProcessCrash(int fd, const Pickle& pickle, void* iter) {
+ void HandleGetTerminationStatus(int fd, const Pickle& pickle, void* iter) {
base::ProcessHandle child;
if (!pickle.ReadInt(&iter, &child)) {
- LOG(WARNING) << "Error parsing DidProcessCrash request from browser";
+ LOG(WARNING) << "Error parsing GetTerminationStatus request "
+ << "from browser";
return;
}
- bool child_exited;
- bool did_crash;
+ base::TerminationStatus status;
+ int exit_code;
if (g_suid_sandbox_active)
child = real_pids_to_sandbox_pids[child];
- if (child)
- did_crash = base::DidProcessCrash(&child_exited, child);
- else
- did_crash = child_exited = false;
+ if (child) {
+ status = base::GetTerminationStatus(child, &exit_code);
+ } else {
+ // Assume that if we can't find the child in the sandbox, then
+ // it terminated normally.
+ status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
+ exit_code = ResultCodes::NORMAL_EXIT;
+ }
Pickle write_pickle;
- write_pickle.WriteBool(did_crash);
- write_pickle.WriteBool(child_exited);
+ write_pickle.WriteInt(static_cast<int>(status));
+ write_pickle.WriteInt(exit_code);
if (HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size())) !=
write_pickle.size()) {
PLOG(ERROR) << "write";