summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorcpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-16 20:47:05 +0000
committercpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-16 20:47:05 +0000
commit66d6c1b14349ebd40e6c7d0a6ae5ececc0695536 (patch)
tree6e54f3d3d769af9369c019d433138b52718943dd /content
parente11c8ee1b8d01092326de43f8b881efb03a7ba0c (diff)
downloadchromium_src-66d6c1b14349ebd40e6c7d0a6ae5ececc0695536.zip
chromium_src-66d6c1b14349ebd40e6c7d0a6ae5ececc0695536.tar.gz
chromium_src-66d6c1b14349ebd40e6c7d0a6ae5ececc0695536.tar.bz2
Trying to reland r101435 : Better account crashes
original code review: http://codereview.chromium.org/7888070 This is the renderer_host piece only. and it is passing all trybots so I am going to land it. TBR=jam BUG=96059 TEST=see bug Review URL: http://codereview.chromium.org/7919022 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@101564 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/renderer_host/browser_render_process_host.cc57
-rw-r--r--content/browser/renderer_host/browser_render_process_host.h21
2 files changed, 62 insertions, 16 deletions
diff --git a/content/browser/renderer_host/browser_render_process_host.cc b/content/browser/renderer_host/browser_render_process_host.cc
index 8578251..8c3034c 100644
--- a/content/browser/renderer_host/browser_render_process_host.cc
+++ b/content/browser/renderer_host/browser_render_process_host.cc
@@ -93,6 +93,7 @@
#if defined(OS_WIN)
#include <objbase.h>
+#include "base/synchronization/waitable_event.h"
#include "content/common/section_util_win.h"
#endif
@@ -650,7 +651,7 @@ bool BrowserRenderProcessHost::FastShutdownIfPossible() {
return false;
child_process_launcher_.reset();
- ProcessDied();
+ ProcessDied(base::TERMINATION_STATUS_NORMAL_TERMINATION, 0, false);
fast_shutdown_started_ = true;
return true;
}
@@ -801,15 +802,6 @@ void BrowserRenderProcessHost::OnChannelConnected(int32 peer_pid) {
}
void BrowserRenderProcessHost::OnChannelError() {
- ProcessDied();
-}
-
-void BrowserRenderProcessHost::ProcessDied() {
- // Our child process has died. If we didn't expect it, it's a crash.
- // In any case, we need to let everyone know it's gone.
- // The OnChannelError notification can fire multiple times due to nested sync
- // calls to a renderer. If we don't have a valid channel here it means we
- // already handled the error.
if (!channel_.get())
return;
@@ -821,15 +813,54 @@ void BrowserRenderProcessHost::ProcessDied() {
child_process_launcher_->GetChildTerminationStatus(&exit_code) :
base::TERMINATION_STATUS_NORMAL_TERMINATION;
+#if defined(OS_WIN)
+ if (!run_renderer_in_process()) {
+ if (status == base::TERMINATION_STATUS_STILL_RUNNING) {
+ HANDLE process = child_process_launcher_->GetHandle();
+ child_process_watcher_.StartWatching(
+ new base::WaitableEvent(process), this);
+ return;
+ }
+ }
+#endif
+ ProcessDied(status, exit_code, false);
+}
+
+// Called when the renderer process handle has been signaled.
+void BrowserRenderProcessHost::OnWaitableEventSignaled(
+ base::WaitableEvent* waitable_event) {
+#if defined (OS_WIN)
+ DCHECK(child_process_launcher_.get());
+ int exit_code = 0;
+ base::TerminationStatus status =
+ child_process_launcher_->GetChildTerminationStatus(&exit_code);
+ ProcessDied(status, exit_code, true);
+#endif
+}
+
+void BrowserRenderProcessHost::ProcessDied(
+ base::TerminationStatus status, int exit_code, bool was_alive) {
+ // Our child process has died. If we didn't expect it, it's a crash.
+ // In any case, we need to let everyone know it's gone.
+ // The OnChannelError notification can fire multiple times due to nested sync
+ // calls to a renderer. If we don't have a valid channel here it means we
+ // already handled the error.
+
if (status == base::TERMINATION_STATUS_PROCESS_CRASHED ||
status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildCrashes",
is_extension_process_ ? 2 : 1);
- }
-
- if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
+ if (was_alive) {
+ UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildCrashesWasAlive",
+ is_extension_process_ ? 2 : 1);
+ }
+ } else if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildKills",
is_extension_process_ ? 2 : 1);
+ if (was_alive) {
+ UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildKillsWasAlive",
+ is_extension_process_ ? 2 : 1);
+ }
}
RendererClosedDetails details(status, exit_code, is_extension_process_);
diff --git a/content/browser/renderer_host/browser_render_process_host.h b/content/browser/renderer_host/browser_render_process_host.h
index 8e95b02..d209b03 100644
--- a/content/browser/renderer_host/browser_render_process_host.h
+++ b/content/browser/renderer_host/browser_render_process_host.h
@@ -12,6 +12,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/process.h"
+#include "base/synchronization/waitable_event_watcher.h"
#include "base/timer.h"
#include "content/browser/child_process_launcher.h"
#include "content/browser/renderer_host/render_process_host.h"
@@ -23,6 +24,7 @@ class RenderWidgetHelper;
namespace base {
class SharedMemory;
+class WaitableEvent;
}
// Implements a concrete RenderProcessHost for the browser process for talking
@@ -40,7 +42,8 @@ class SharedMemory;
// are correlated with IDs. This way, the Views and the corresponding ViewHosts
// communicate through the two process objects.
class BrowserRenderProcessHost : public RenderProcessHost,
- public ChildProcessLauncher::Client {
+ public ChildProcessLauncher::Client,
+ public base::WaitableEventWatcher::Delegate {
public:
explicit BrowserRenderProcessHost(content::BrowserContext* browser_context);
virtual ~BrowserRenderProcessHost();
@@ -76,6 +79,10 @@ class BrowserRenderProcessHost : public RenderProcessHost,
// ChildProcessLauncher::Client implementation.
virtual void OnProcessLaunched();
+ // base::WaitableEventWatcher::Delegate implementation.
+ virtual void OnWaitableEventSignaled(
+ base::WaitableEvent* waitable_event) OVERRIDE;
+
private:
friend class VisitRelayingRenderProcessHost;
@@ -102,8 +109,11 @@ class BrowserRenderProcessHost : public RenderProcessHost,
// Callers can reduce the RenderProcess' priority.
void SetBackgrounded(bool backgrounded);
- // Handle termination of our process.
- void ProcessDied();
+ // Handle termination of our process. |was_alive| indicates that when we
+ // tried to retrieve the exit code the process had not finished yet.
+ void ProcessDied(base::TerminationStatus status,
+ int exit_code,
+ bool was_alive);
// The count of currently visible widgets. Since the host can be a container
// for multiple widgets, it uses this count to determine when it should be
@@ -150,6 +160,11 @@ class BrowserRenderProcessHost : public RenderProcessHost,
// because the queued messages may have dependencies on the init messages.
std::queue<IPC::Message*> queued_messages_;
+#if defined(OS_WIN)
+ // Used to wait until the renderer dies to get an accurrate exit code.
+ base::WaitableEventWatcher child_process_watcher_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(BrowserRenderProcessHost);
};