Commit 22e2f4a2 authored by wfh's avatar wfh Committed by Commit bot

Add extra parameter to BrowserChildProcessCrashed to pass the exit_code at...

Add extra parameter to BrowserChildProcessCrashed to pass the exit_code at time of crash/termination.

Wire this into all the existing callers.

Add a new child process watcher in chrome to be notified on child process crashes. This will confirm whether users with RESULT_CODE_INVALID_SANDBOX_STATE are crashing on background start (--no-startup-window) or not. This also adds required framework to paint a sad tab UI from this class in the future.

BUG=472324, 453541
TEST=Apply patch in http://pastebin.com/uEDxngBa and verify histogram ChildProcess.InvalidSandboxStateCrash.NoStartupWindow is recorded.

Review URL: https://codereview.chromium.org/1067733006

Cr-Commit-Position: refs/heads/master@{#327380}
parent 7c64f265
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "base/time/default_tick_clock.h" #include "base/time/default_tick_clock.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "chrome/browser/chrome_browser_main.h" #include "chrome/browser/chrome_browser_main.h"
#include "chrome/browser/chrome_child_process_watcher.h"
#include "chrome/browser/chrome_content_browser_client.h" #include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/component_updater/chrome_component_updater_configurator.h" #include "chrome/browser/component_updater/chrome_component_updater_configurator.h"
...@@ -273,6 +274,8 @@ void BrowserProcessImpl::StartTearDown() { ...@@ -273,6 +274,8 @@ void BrowserProcessImpl::StartTearDown() {
// the IO thread. // the IO thread.
promo_resource_service_.reset(); promo_resource_service_.reset();
child_process_watcher_.reset();
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
// Debugger must be cleaned up before IO thread and NotificationService. // Debugger must be cleaned up before IO thread and NotificationService.
remote_debugging_server_.reset(); remote_debugging_server_.reset();
...@@ -1061,6 +1064,8 @@ void BrowserProcessImpl::PreMainMessageLoopRun() { ...@@ -1061,6 +1064,8 @@ void BrowserProcessImpl::PreMainMessageLoopRun() {
storage_monitor::StorageMonitor::Create(); storage_monitor::StorageMonitor::Create();
#endif #endif
child_process_watcher_.reset(new ChromeChildProcessWatcher());
platform_part_->PreMainMessageLoopRun(); platform_part_->PreMainMessageLoopRun();
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
class ChromeChildProcessWatcher;
class ChromeDeviceClient; class ChromeDeviceClient;
class ChromeNetLog; class ChromeNetLog;
class ChromeResourceDispatcherHostDelegate; class ChromeResourceDispatcherHostDelegate;
...@@ -301,6 +302,8 @@ class BrowserProcessImpl : public BrowserProcess, ...@@ -301,6 +302,8 @@ class BrowserProcessImpl : public BrowserProcess,
scoped_ptr<gcm::GCMDriver> gcm_driver_; scoped_ptr<gcm::GCMDriver> gcm_driver_;
scoped_ptr<ChromeChildProcessWatcher> child_process_watcher_;
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
scoped_ptr<ChromeDeviceClient> device_client_; scoped_ptr<ChromeDeviceClient> device_client_;
#endif #endif
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chrome_child_process_watcher.h"
#include "base/command_line.h"
#include "base/metrics/histogram.h"
#include "chrome/common/chrome_result_codes.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/browser_child_process_observer.h"
#include "content/public/browser/child_process_data.h"
namespace {
void AnalyzeCrash(int exit_code) {
if (exit_code == chrome::RESULT_CODE_INVALID_SANDBOX_STATE) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
const bool no_startup_window =
command_line->HasSwitch(switches::kNoStartupWindow);
UMA_HISTOGRAM_BOOLEAN(
"ChildProcess.InvalidSandboxStateCrash.NoStartupWindow",
no_startup_window);
}
}
} // namespace
ChromeChildProcessWatcher::ChromeChildProcessWatcher() {
BrowserChildProcessObserver::Add(this);
}
ChromeChildProcessWatcher::~ChromeChildProcessWatcher() {
BrowserChildProcessObserver::Remove(this);
}
void ChromeChildProcessWatcher::BrowserChildProcessCrashed(
const content::ChildProcessData& data,
int exit_code) {
AnalyzeCrash(exit_code);
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROME_CHILD_PROCESS_WATCHER_H_
#define CHROME_BROWSER_CHROME_CHILD_PROCESS_WATCHER_H_
#include "base/basictypes.h"
#include "content/public/browser/browser_child_process_observer.h"
// ChromeChildProcessWatcher watches for crashed child processes.
class ChromeChildProcessWatcher : public content::BrowserChildProcessObserver {
public:
ChromeChildProcessWatcher();
~ChromeChildProcessWatcher() override;
private:
// content::BrowserChildProcessObserver:
void BrowserChildProcessCrashed(const content::ChildProcessData& data,
int exit_code) override;
DISALLOW_COPY_AND_ASSIGN(ChromeChildProcessWatcher);
};
#endif // CHROME_BROWSER_CHROME_CHILD_PROCESS_WATCHER_H_
...@@ -236,7 +236,8 @@ void ChromeStabilityMetricsProvider::Observe( ...@@ -236,7 +236,8 @@ void ChromeStabilityMetricsProvider::Observe(
} }
void ChromeStabilityMetricsProvider::BrowserChildProcessCrashed( void ChromeStabilityMetricsProvider::BrowserChildProcessCrashed(
const content::ChildProcessData& data) { const content::ChildProcessData& data,
int exit_code) {
#if defined(ENABLE_PLUGINS) #if defined(ENABLE_PLUGINS)
// Exclude plugin crashes from the count below because we report them via // Exclude plugin crashes from the count below because we report them via
// a separate UMA metric. // a separate UMA metric.
......
...@@ -48,7 +48,8 @@ class ChromeStabilityMetricsProvider ...@@ -48,7 +48,8 @@ class ChromeStabilityMetricsProvider
// content::BrowserChildProcessObserver: // content::BrowserChildProcessObserver:
void BrowserChildProcessCrashed( void BrowserChildProcessCrashed(
const content::ChildProcessData& data) override; const content::ChildProcessData& data,
int exit_code) override;
// Logs the initiation of a page load and uses |web_contents| to do // Logs the initiation of a page load and uses |web_contents| to do
// additional logging of the type of page loaded. // additional logging of the type of page loaded.
......
...@@ -353,7 +353,8 @@ void PluginMetricsProvider::BrowserChildProcessHostConnected( ...@@ -353,7 +353,8 @@ void PluginMetricsProvider::BrowserChildProcessHostConnected(
} }
void PluginMetricsProvider::BrowserChildProcessCrashed( void PluginMetricsProvider::BrowserChildProcessCrashed(
const content::ChildProcessData& data) { const content::ChildProcessData& data,
int exit_code) {
GetChildProcessStats(data).process_crashes++; GetChildProcessStats(data).process_crashes++;
RecordCurrentStateWithDelay(kRecordStateDelayMs); RecordCurrentStateWithDelay(kRecordStateDelayMs);
} }
......
...@@ -90,8 +90,8 @@ class PluginMetricsProvider : public metrics::MetricsProvider, ...@@ -90,8 +90,8 @@ class PluginMetricsProvider : public metrics::MetricsProvider,
// content::BrowserChildProcessObserver: // content::BrowserChildProcessObserver:
void BrowserChildProcessHostConnected( void BrowserChildProcessHostConnected(
const content::ChildProcessData& data) override; const content::ChildProcessData& data) override;
void BrowserChildProcessCrashed( void BrowserChildProcessCrashed(const content::ChildProcessData& data,
const content::ChildProcessData& data) override; int exit_code) override;
void BrowserChildProcessInstanceCreated( void BrowserChildProcessInstanceCreated(
const content::ChildProcessData& data) override; const content::ChildProcessData& data) override;
......
...@@ -268,6 +268,8 @@ ...@@ -268,6 +268,8 @@
'browser/chrome_browser_main_mac.mm', 'browser/chrome_browser_main_mac.mm',
'browser/chrome_browser_main_win.cc', 'browser/chrome_browser_main_win.cc',
'browser/chrome_browser_main_win.h', 'browser/chrome_browser_main_win.h',
'browser/chrome_child_process_watcher.cc',
'browser/chrome_child_process_watcher.h',
'browser/chrome_content_browser_client.cc', 'browser/chrome_content_browser_client.cc',
'browser/chrome_content_browser_client.h', 'browser/chrome_content_browser_client.h',
'browser/chrome_content_browser_client_parts.h', 'browser/chrome_content_browser_client_parts.h',
......
...@@ -140,7 +140,8 @@ void CastStabilityMetricsProvider::Observe( ...@@ -140,7 +140,8 @@ void CastStabilityMetricsProvider::Observe(
} }
void CastStabilityMetricsProvider::BrowserChildProcessCrashed( void CastStabilityMetricsProvider::BrowserChildProcessCrashed(
const content::ChildProcessData& data) { const content::ChildProcessData& data,
int exit_code) {
IncrementPrefValue(prefs::kStabilityChildProcessCrashCount); IncrementPrefValue(prefs::kStabilityChildProcessCrashCount);
} }
......
...@@ -57,7 +57,8 @@ class CastStabilityMetricsProvider ...@@ -57,7 +57,8 @@ class CastStabilityMetricsProvider
// content::BrowserChildProcessObserver implementation: // content::BrowserChildProcessObserver implementation:
void BrowserChildProcessCrashed( void BrowserChildProcessCrashed(
const content::ChildProcessData& data) override; const content::ChildProcessData& data,
int exit_code) override;
// Records a renderer process crash. // Records a renderer process crash.
void LogRendererCrash(content::RenderProcessHost* host, void LogRendererCrash(content::RenderProcessHost* host,
......
...@@ -126,7 +126,8 @@ void CrashDumpManager::BrowserChildProcessHostDisconnected( ...@@ -126,7 +126,8 @@ void CrashDumpManager::BrowserChildProcessHostDisconnected(
} }
void CrashDumpManager::BrowserChildProcessCrashed( void CrashDumpManager::BrowserChildProcessCrashed(
const content::ChildProcessData& data) { const content::ChildProcessData& data,
int exit_code) {
OnChildExit(data.id, data.handle); OnChildExit(data.id, data.handle);
} }
......
...@@ -55,7 +55,8 @@ class CrashDumpManager : public content::BrowserChildProcessObserver, ...@@ -55,7 +55,8 @@ class CrashDumpManager : public content::BrowserChildProcessObserver,
void BrowserChildProcessHostDisconnected( void BrowserChildProcessHostDisconnected(
const content::ChildProcessData& data) override; const content::ChildProcessData& data) override;
void BrowserChildProcessCrashed( void BrowserChildProcessCrashed(
const content::ChildProcessData& data) override; const content::ChildProcessData& data,
int exit_code) override;
// NotificationObserver implementation: // NotificationObserver implementation:
void Observe(int type, void Observe(int type,
......
...@@ -31,7 +31,9 @@ class BootstrapSandboxPolicy : public BrowserChildProcessObserver { ...@@ -31,7 +31,9 @@ class BootstrapSandboxPolicy : public BrowserChildProcessObserver {
// BrowserChildProcessObserver: // BrowserChildProcessObserver:
void BrowserChildProcessHostDisconnected( void BrowserChildProcessHostDisconnected(
const ChildProcessData& data) override; const ChildProcessData& data) override;
void BrowserChildProcessCrashed(const ChildProcessData& data) override; void BrowserChildProcessCrashed(
const ChildProcessData& data,
int exit_code) override;
private: private:
friend struct DefaultSingletonTraits<BootstrapSandboxPolicy>; friend struct DefaultSingletonTraits<BootstrapSandboxPolicy>;
...@@ -53,7 +55,8 @@ void BootstrapSandboxPolicy::BrowserChildProcessHostDisconnected( ...@@ -53,7 +55,8 @@ void BootstrapSandboxPolicy::BrowserChildProcessHostDisconnected(
} }
void BootstrapSandboxPolicy::BrowserChildProcessCrashed( void BootstrapSandboxPolicy::BrowserChildProcessCrashed(
const ChildProcessData& data) { const ChildProcessData& data,
int exit_code) {
sandbox()->ChildDied(data.handle); sandbox()->ChildDied(data.handle);
} }
......
...@@ -53,9 +53,9 @@ void NotifyProcessHostDisconnected(const ChildProcessData& data) { ...@@ -53,9 +53,9 @@ void NotifyProcessHostDisconnected(const ChildProcessData& data) {
BrowserChildProcessHostDisconnected(data)); BrowserChildProcessHostDisconnected(data));
} }
void NotifyProcessCrashed(const ChildProcessData& data) { void NotifyProcessCrashed(const ChildProcessData& data, int exit_code) {
FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(), FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(),
BrowserChildProcessCrashed(data)); BrowserChildProcessCrashed(data, exit_code));
} }
} // namespace } // namespace
...@@ -282,8 +282,9 @@ void BrowserChildProcessHostImpl::OnChildDisconnected() { ...@@ -282,8 +282,9 @@ void BrowserChildProcessHostImpl::OnChildDisconnected() {
case base::TERMINATION_STATUS_PROCESS_CRASHED: case base::TERMINATION_STATUS_PROCESS_CRASHED:
case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: { case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: {
delegate_->OnProcessCrashed(exit_code); delegate_->OnProcessCrashed(exit_code);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, BrowserThread::PostTask(
base::Bind(&NotifyProcessCrashed, data_)); BrowserThread::UI, FROM_HERE,
base::Bind(&NotifyProcessCrashed, data_, exit_code));
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Crashed2", UMA_HISTOGRAM_ENUMERATION("ChildProcess.Crashed2",
data_.process_type, data_.process_type,
PROCESS_TYPE_MAX); PROCESS_TYPE_MAX);
......
...@@ -69,7 +69,8 @@ class CONTENT_EXPORT MachBroker : public base::ProcessMetrics::PortProvider, ...@@ -69,7 +69,8 @@ class CONTENT_EXPORT MachBroker : public base::ProcessMetrics::PortProvider,
// Implement |BrowserChildProcessObserver|. // Implement |BrowserChildProcessObserver|.
void BrowserChildProcessHostDisconnected( void BrowserChildProcessHostDisconnected(
const ChildProcessData& data) override; const ChildProcessData& data) override;
void BrowserChildProcessCrashed(const ChildProcessData& data) override; void BrowserChildProcessCrashed(const ChildProcessData& data,
int exit_code) override;
// Implement |NotificationObserver|. // Implement |NotificationObserver|.
void Observe(int type, void Observe(int type,
......
...@@ -217,7 +217,8 @@ void MachBroker::BrowserChildProcessHostDisconnected( ...@@ -217,7 +217,8 @@ void MachBroker::BrowserChildProcessHostDisconnected(
InvalidateChildProcessId(data.id); InvalidateChildProcessId(data.id);
} }
void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data) { void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data,
int exit_code) {
InvalidateChildProcessId(data.id); InvalidateChildProcessId(data.id);
} }
......
...@@ -24,7 +24,9 @@ class CONTENT_EXPORT BrowserChildProcessObserver { ...@@ -24,7 +24,9 @@ class CONTENT_EXPORT BrowserChildProcessObserver {
const ChildProcessData& data) {} const ChildProcessData& data) {}
// Called when a child process disappears unexpectedly as a result of a crash. // Called when a child process disappears unexpectedly as a result of a crash.
virtual void BrowserChildProcessCrashed(const ChildProcessData& data) {} // |exit_code| contains the exit code from the process.
virtual void BrowserChildProcessCrashed(const ChildProcessData& data,
int exit_code) {}
// Called when an instance of a particular child is created in a page. If one // Called when an instance of a particular child is created in a page. If one
// page contains several regions rendered by the same child, this will be // page contains several regions rendered by the same child, this will be
......
...@@ -30,9 +30,15 @@ struct ChildProcessData { ...@@ -30,9 +30,15 @@ struct ChildProcessData {
// current process. // current process.
base::ProcessHandle handle; base::ProcessHandle handle;
// The exit code for the process. This is only valid for processes that have
// already exited e.g. when receiving a BrowserChildProcessCrashed callback.
int exit_code;
explicit ChildProcessData(int process_type) explicit ChildProcessData(int process_type)
: process_type(process_type), id(0), handle(base::kNullProcessHandle) { : process_type(process_type),
} id(0),
handle(base::kNullProcessHandle),
exit_code(0) {}
}; };
} // namespace content } // namespace content
......
...@@ -2772,6 +2772,17 @@ Therefore, the affected-histogram name has to have at least one dot in it. ...@@ -2772,6 +2772,17 @@ Therefore, the affected-histogram name has to have at least one dot in it.
</summary> </summary>
</histogram> </histogram>
<histogram name="ChildProcess.InvalidSandboxStateCrash.NoStartupWindow"
enum="BooleanPresent">
<owner>wfh@chromium.org</owner>
<summary>
Whether the browser command line had the switch --no-startup-window when a
child process crashed due to invalid sandbox state. Recorded when a child
process crashes if the exit code from the child process is
RESULT_CODE_INVALID_SANDBOX_STATE.
</summary>
</histogram>
<histogram name="ChildProcess.Killed" enum="ProcessType"> <histogram name="ChildProcess.Killed" enum="ProcessType">
<obsolete> <obsolete>
Deprecated 3/2013. Renamed to ChildProcess.Killed2. Deprecated 3/2013. Renamed to ChildProcess.Killed2.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment