summaryrefslogtreecommitdiffstats
path: root/content/browser/browser_child_process_host.cc
diff options
context:
space:
mode:
authorcpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-16 23:07:05 +0000
committercpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-16 23:07:05 +0000
commita3a7e2c07a1dcac13b004257982bb174e681693c (patch)
tree4eaaaff74dd1ca3c96d93c15d1b9123bbdd77e83 /content/browser/browser_child_process_host.cc
parentc0bcb01f4d832c493e320198ac31f31cc067fc5d (diff)
downloadchromium_src-a3a7e2c07a1dcac13b004257982bb174e681693c.zip
chromium_src-a3a7e2c07a1dcac13b004257982bb174e681693c.tar.gz
chromium_src-a3a7e2c07a1dcac13b004257982bb174e681693c.tar.bz2
Trying to reland r101435 : Better account crashes for the BrowserChildProcessHost
original code review: http://codereview.chromium.org/7888070 In this change we remove renderer_host piece, which I landed already and fixes the problem which was a missing break (line 170, see patch set 2). TBR=jam BUG=96059 TEST=see bug Review URL: http://codereview.chromium.org/7919016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@101595 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/browser_child_process_host.cc')
-rw-r--r--content/browser/browser_child_process_host.cc95
1 files changed, 67 insertions, 28 deletions
diff --git a/content/browser/browser_child_process_host.cc b/content/browser/browser_child_process_host.cc
index 40b6598..184ac82 100644
--- a/content/browser/browser_child_process_host.cc
+++ b/content/browser/browser_child_process_host.cc
@@ -23,6 +23,10 @@
#include "content/common/process_watcher.h"
#include "content/common/result_codes.h"
+#if defined(OS_WIN)
+#include "base/synchronization/waitable_event.h"
+#endif // OS_WIN
+
namespace {
typedef std::list<BrowserChildProcessHost*> ChildProcessList;
@@ -54,7 +58,8 @@ class ChildNotificationTask : public Task {
BrowserChildProcessHost::BrowserChildProcessHost(
ChildProcessInfo::ProcessType type)
: ChildProcessInfo(type, -1),
- ALLOW_THIS_IN_INITIALIZER_LIST(client_(this)) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(client_(this)),
+ disconnect_was_alive_(false) {
AddFilter(new TraceMessageFilter);
g_child_process_list.Get().push_back(this);
@@ -123,37 +128,71 @@ base::TerminationStatus BrowserChildProcessHost::GetChildTerminationStatus(
return child_process_->GetChildTerminationStatus(exit_code);
}
-void BrowserChildProcessHost::OnChildDied() {
- // This may be called by both the channel's OnChannelError handler
- // as well as the process launcher's OnProcessLaunched handler.
- if (handle() != base::kNullProcessHandle) {
- int exit_code;
- base::TerminationStatus status = GetChildTerminationStatus(&exit_code);
- switch (status) {
- case base::TERMINATION_STATUS_PROCESS_CRASHED:
- case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: {
- OnProcessCrashed(exit_code);
-
- // Report that this child process crashed.
- Notify(content::NOTIFICATION_CHILD_PROCESS_CRASHED);
- UMA_HISTOGRAM_COUNTS("ChildProcess.Crashes", this->type());
- break;
+// The ChildProcessHost default implementation calls OnChildDied() always
+// but at this layer and below we need to have the final child process exit
+// code to properly bucket crashes vs kills. At least on Windows we can do
+// this if we wait until the process handle is signaled, however this means
+// that this function can be called twice: once from the actual channel error
+// and once from OnWaitableEventSignaled().
+void BrowserChildProcessHost::OnChildDisconnected() {
+ DCHECK(handle() != base::kNullProcessHandle);
+ int exit_code;
+ base::TerminationStatus status = GetChildTerminationStatus(&exit_code);
+ switch (status) {
+ case base::TERMINATION_STATUS_PROCESS_CRASHED:
+ case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: {
+ OnProcessCrashed(exit_code);
+ // Report that this child process crashed.
+ Notify(content::NOTIFICATION_CHILD_PROCESS_CRASHED);
+ UMA_HISTOGRAM_COUNTS("ChildProcess.Crashes", this->type());
+ if (disconnect_was_alive_) {
+ UMA_HISTOGRAM_COUNTS("ChildProcess.CrashesWasAlive", this->type());
}
- case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: {
- OnProcessWasKilled(exit_code);
-
- // Report that this child process was killed.
- Notify(content::NOTIFICATION_CHILD_PROCESS_WAS_KILLED);
- UMA_HISTOGRAM_COUNTS("ChildProcess.Kills", this->type());
- break;
+ break;
+ }
+ case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: {
+ OnProcessWasKilled(exit_code);
+ // Report that this child process was killed.
+ Notify(content::NOTIFICATION_CHILD_PROCESS_WAS_KILLED);
+ UMA_HISTOGRAM_COUNTS("ChildProcess.Kills", this->type());
+ if (disconnect_was_alive_) {
+ UMA_HISTOGRAM_COUNTS("ChildProcess.KillsWasAlive", this->type());
}
- default:
- break;
+ break;
}
- // Notify in the main loop of the disconnection.
- Notify(content::NOTIFICATION_CHILD_PROCESS_HOST_DISCONNECTED);
+ case base::TERMINATION_STATUS_STILL_RUNNING: {
+ // exit code not yet available.
+ disconnect_was_alive_ = true;
+#if defined(OS_WIN)
+ child_watcher_.StartWatching(new base::WaitableEvent(handle()), this);
+ return;
+#else
+ break;
+#endif
+ }
+
+ default:
+ break;
}
- ChildProcessHost::OnChildDied();
+ // Notify in the main loop of the disconnection.
+ Notify(content::NOTIFICATION_CHILD_PROCESS_HOST_DISCONNECTED);
+ OnChildDied();
+}
+
+// The child process handle has been signaled so the exit code is finally
+// available. Unfortunately STILL_ACTIVE (0x103) is a valid exit code in
+// which case we should not call OnChildDisconnected() or else we will be
+// waiting forever.
+void BrowserChildProcessHost::OnWaitableEventSignaled(
+ base::WaitableEvent* waitable_event) {
+#if defined (OS_WIN)
+ unsigned long exit_code = 0;
+ GetExitCodeProcess(waitable_event->Release(), &exit_code);
+ delete waitable_event;
+ if (exit_code == STILL_ACTIVE)
+ OnChildDied();
+ BrowserChildProcessHost::OnChildDisconnected();
+#endif
}
void BrowserChildProcessHost::ShutdownStarted() {