summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/process.h1
-rw-r--r--chrome/browser/metrics/metrics_service_uitest.cc12
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc13
-rw-r--r--chrome/browser/zygote_host_linux.cc35
-rw-r--r--chrome/browser/zygote_host_linux.h15
-rw-r--r--chrome/browser/zygote_main_linux.cc45
-rw-r--r--chrome/chrome.gyp1
7 files changed, 98 insertions, 24 deletions
diff --git a/base/process.h b/base/process.h
index 312f84c..459ad58 100644
--- a/base/process.h
+++ b/base/process.h
@@ -6,6 +6,7 @@
#define BASE_PROCESS_H_
#include "base/basictypes.h"
+#include "build/build_config.h"
#include <sys/types.h>
#ifdef OS_WIN
diff --git a/chrome/browser/metrics/metrics_service_uitest.cc b/chrome/browser/metrics/metrics_service_uitest.cc
index 7245a35..9f5f7e7 100644
--- a/chrome/browser/metrics/metrics_service_uitest.cc
+++ b/chrome/browser/metrics/metrics_service_uitest.cc
@@ -90,14 +90,8 @@ TEST_F(MetricsServiceTest, CrashRenderers) {
// kill the process for one of the tabs
scoped_refptr<TabProxy> tab(window_->GetTab(1));
ASSERT_TRUE(tab.get());
- int process_id = 0;
- ASSERT_TRUE(tab->GetProcessID(&process_id));
- ASSERT_NE(0, process_id);
- base::ProcessHandle process_handle;
- ASSERT_TRUE(base::OpenProcessHandle(process_id, &process_handle));
- // Fake Access Violation.
- base::KillProcess(process_handle, 0xc0000005, true);
- base::CloseProcessHandle(process_handle);
+
+ tab->NavigateToURLAsync(GURL("about:crash"));
// Give the browser a chance to notice the crashed tab.
PlatformThread::Sleep(1000);
@@ -111,6 +105,6 @@ TEST_F(MetricsServiceTest, CrashRenderers) {
local_state->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0);
EXPECT_TRUE(local_state->GetBoolean(prefs::kStabilityExitedCleanly));
EXPECT_EQ(1, local_state->GetInteger(prefs::kStabilityLaunchCount));
- EXPECT_EQ(3, local_state->GetInteger(prefs::kStabilityPageLoadCount));
+ EXPECT_EQ(4, local_state->GetInteger(prefs::kStabilityPageLoadCount));
EXPECT_EQ(1, local_state->GetInteger(prefs::kStabilityRendererCrashCount));
}
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index 29e7ef0..06405ed 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -721,7 +721,18 @@ void BrowserRenderProcessHost::OnChannelError() {
DCHECK(channel_.get());
bool child_exited;
- bool did_crash = base::DidProcessCrash(&child_exited, process_.handle());
+ bool did_crash;
+ if (zygote_child_) {
+#if defined(OS_LINUX)
+ did_crash = Singleton<ZygoteHost>()->DidProcessCrash(
+ process_.handle(), &child_exited);
+#else
+ NOTREACHED();
+ did_crash = true;
+#endif
+ } else {
+ did_crash = base::DidProcessCrash(&child_exited, process_.handle());
+ }
NotificationService::current()->Notify(
NotificationType::RENDERER_PROCESS_CLOSED,
diff --git a/chrome/browser/zygote_host_linux.cc b/chrome/browser/zygote_host_linux.cc
index 1c582a3..230373c 100644
--- a/chrome/browser/zygote_host_linux.cc
+++ b/chrome/browser/zygote_host_linux.cc
@@ -94,3 +94,38 @@ void ZygoteHost::EnsureProcessTerminated(pid_t process) {
HANDLE_EINTR(write(control_fd_, pickle.data(), pickle.size()));
}
+
+bool ZygoteHost::DidProcessCrash(base::ProcessHandle handle,
+ bool* child_exited) {
+ Pickle pickle;
+ pickle.WriteInt(kCmdDidProcessCrash);
+ pickle.WriteInt(handle);
+
+ HANDLE_EINTR(write(control_fd_, pickle.data(), pickle.size()));
+
+ static const unsigned kMaxMessageLength = 128;
+ char buf[kMaxMessageLength];
+ const ssize_t len = HANDLE_EINTR(read(control_fd_, buf, sizeof(buf)));
+
+ if (len == -1) {
+ LOG(WARNING) << "Error reading message from zygote: " << errno;
+ return false;
+ } else if (len == 0) {
+ LOG(WARNING) << "Socket closed prematurely.";
+ return false;
+ }
+
+ Pickle read_pickle(buf, len);
+ bool did_crash, tmp_child_exited;
+ 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 (child_exited)
+ *child_exited = tmp_child_exited;
+
+ return did_crash;
+}
diff --git a/chrome/browser/zygote_host_linux.h b/chrome/browser/zygote_host_linux.h
index 279918d..94ac92e 100644
--- a/chrome/browser/zygote_host_linux.h
+++ b/chrome/browser/zygote_host_linux.h
@@ -9,7 +9,10 @@
#include <vector>
#include "base/global_descriptors_posix.h"
-#include "base/singleton.h"
+#include "base/process.h"
+
+template<typename Type>
+struct DefaultSingletonTraits;
// http://code.google.com/p/chromium/wiki/LinuxZygote
@@ -23,11 +26,17 @@ 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);
+
// 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.
+ kCmdFork = 0, // Fork off a new renderer.
+ kCmdReap = 1, // Reap a renderer child.
+ kCmdDidProcessCrash = 2, // Check if child process crashed.
};
private:
diff --git a/chrome/browser/zygote_main_linux.cc b/chrome/browser/zygote_main_linux.cc
index 6d15c0f..ba550d9 100644
--- a/chrome/browser/zygote_main_linux.cc
+++ b/chrome/browser/zygote_main_linux.cc
@@ -77,18 +77,24 @@ class Zygote {
void* iter = NULL;
int kind;
- if (!pickle.ReadInt(&iter, &kind))
- goto error;
-
- if (kind == ZygoteHost::kCmdFork) {
- return HandleForkRequest(fd, pickle, iter, fds);
- } else if (kind == ZygoteHost::kCmdReap) {
- if (fds.size())
- goto error;
- return HandleReapRequest(fd, pickle, iter);
+ if (pickle.ReadInt(&iter, &kind)) {
+ switch (kind) {
+ case ZygoteHost::kCmdFork:
+ return HandleForkRequest(fd, pickle, iter, fds);
+ case ZygoteHost::kCmdReap:
+ if (!fds.empty())
+ break;
+ return HandleReapRequest(fd, pickle, iter);
+ case ZygoteHost::kCmdDidProcessCrash:
+ if (!fds.empty())
+ break;
+ return HandleDidProcessCrash(fd, pickle, iter);
+ default:
+ NOTREACHED();
+ break;
+ }
}
- error:
LOG(WARNING) << "Error parsing message from browser";
for (std::vector<int>::const_iterator
i = fds.begin(); i != fds.end(); ++i)
@@ -109,6 +115,25 @@ class Zygote {
return false;
}
+ bool HandleDidProcessCrash(int fd, Pickle& pickle, void* iter) {
+ base::ProcessHandle child;
+
+ if (!pickle.ReadInt(&iter, &child)) {
+ LOG(WARNING) << "Error parsing DidProcessCrash request from browser";
+ return false;
+ }
+
+ bool child_exited;
+ bool did_crash = base::DidProcessCrash(&child_exited, child);
+
+ Pickle write_pickle;
+ write_pickle.WriteBool(did_crash);
+ write_pickle.WriteBool(child_exited);
+ HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size()));
+
+ return false;
+ }
+
// Handle a 'fork' request from the browser: this means that the browser
// wishes to start a new renderer.
bool HandleForkRequest(int fd, Pickle& pickle, void* iter,
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 51b9118..8c0a95a 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -3170,7 +3170,6 @@
# TODO(port)
'browser/crash_recovery_uitest.cc',
'browser/login_prompt_uitest.cc',
- 'browser/metrics/metrics_service_uitest.cc',
'browser/renderer_host/resource_dispatcher_host_uitest.cc',
'test/reliability/page_load_test.cc',
'test/ui/layout_plugin_uitest.cc',