summaryrefslogtreecommitdiffstats
path: root/ppapi/native_client
diff options
context:
space:
mode:
authorsehr@chromium.org <sehr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-09 20:21:22 +0000
committersehr@chromium.org <sehr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-09 20:21:22 +0000
commitdfe329914ef7776edf93e070afbec277841acb5d (patch)
tree7d0ac2840ae9c81437783d23c7a6255e5102b525 /ppapi/native_client
parent34187c0e73005ccb1fd24b466af96006a07404dd (diff)
downloadchromium_src-dfe329914ef7776edf93e070afbec277841acb5d.zip
chromium_src-dfe329914ef7776edf93e070afbec277841acb5d.tar.gz
chromium_src-dfe329914ef7776edf93e070afbec277841acb5d.tar.bz2
Implement PNaCl crash throttling
Keep a short vector of crash times. When the vector is full, check that the crashes occurred within a specified interval. If so, cause PNaCl loads to fail. BUG= https://code.google.com/p/nativeclient/issues/detail?id=359 R=dmichael@chromium.org, jln@chromium.org Review URL: https://codereview.chromium.org/22459002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@216742 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/native_client')
-rw-r--r--ppapi/native_client/src/trusted/plugin/module_ppapi.cc120
-rw-r--r--ppapi/native_client/src/trusted/plugin/module_ppapi.h45
-rw-r--r--ppapi/native_client/src/trusted/plugin/plugin.cc33
-rw-r--r--ppapi/native_client/src/trusted/plugin/plugin_error.h1
4 files changed, 137 insertions, 62 deletions
diff --git a/ppapi/native_client/src/trusted/plugin/module_ppapi.cc b/ppapi/native_client/src/trusted/plugin/module_ppapi.cc
index 90fe0f1..4204ed4 100644
--- a/ppapi/native_client/src/trusted/plugin/module_ppapi.cc
+++ b/ppapi/native_client/src/trusted/plugin/module_ppapi.cc
@@ -8,81 +8,95 @@
#include "native_client/src/shared/platform/nacl_time.h"
#include "native_client/src/trusted/desc/nrd_all_modules.h"
-#include "ppapi/c/private/ppb_nacl_private.h"
-#include "ppapi/cpp/module.h"
+#include "ppapi/native_client/src/trusted/plugin/module_ppapi.h"
#include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h"
#include "ppapi/native_client/src/trusted/plugin/plugin.h"
namespace plugin {
-class ModulePpapi : public pp::Module {
- public:
- ModulePpapi() : pp::Module(),
- init_was_successful_(false),
- private_interface_(NULL) {
- MODULE_PRINTF(("ModulePpapi::ModulePpapi (this=%p)\n",
- static_cast<void*>(this)));
- }
+ModulePpapi::ModulePpapi() : pp::Module(),
+ init_was_successful_(false),
+ private_interface_(NULL) {
+ MODULE_PRINTF(("ModulePpapi::ModulePpapi (this=%p)\n",
+ static_cast<void*>(this)));
+}
- virtual ~ModulePpapi() {
- if (init_was_successful_) {
- NaClSrpcModuleFini();
- NaClNrdAllModulesFini();
- }
- MODULE_PRINTF(("ModulePpapi::~ModulePpapi (this=%p)\n",
- static_cast<void*>(this)));
+ModulePpapi::~ModulePpapi() {
+ if (init_was_successful_) {
+ NaClSrpcModuleFini();
+ NaClNrdAllModulesFini();
}
+ MODULE_PRINTF(("ModulePpapi::~ModulePpapi (this=%p)\n",
+ static_cast<void*>(this)));
+}
- virtual bool Init() {
- // Ask the browser for an interface which provides missing functions
- private_interface_ = reinterpret_cast<const PPB_NaCl_Private*>(
- GetBrowserInterface(PPB_NACL_PRIVATE_INTERFACE));
+bool ModulePpapi::Init() {
+ // Ask the browser for an interface which provides missing functions
+ private_interface_ = reinterpret_cast<const PPB_NaCl_Private*>(
+ GetBrowserInterface(PPB_NACL_PRIVATE_INTERFACE));
- if (NULL == private_interface_) {
- MODULE_PRINTF(("ModulePpapi::Init failed: "
- "GetBrowserInterface returned NULL\n"));
- return false;
- }
+ if (NULL == private_interface_) {
+ MODULE_PRINTF(("ModulePpapi::Init failed: "
+ "GetBrowserInterface returned NULL\n"));
+ return false;
+ }
- launch_nacl_process = reinterpret_cast<LaunchNaClProcessFunc>(
- private_interface_->LaunchSelLdr);
+ launch_nacl_process = reinterpret_cast<LaunchNaClProcessFunc>(
+ private_interface_->LaunchSelLdr);
#if NACL_LINUX || NACL_OSX
- // Note that currently we do not need random numbers inside the
- // NaCl trusted plugin on Unix, but NaClSecureRngModuleInit() is
- // strict and will raise a fatal error unless we provide it with a
- // /dev/urandom FD beforehand.
- NaClSecureRngModuleSetUrandomFd(dup(private_interface_->UrandomFD()));
+ // Note that currently we do not need random numbers inside the
+ // NaCl trusted plugin on Unix, but NaClSecureRngModuleInit() is
+ // strict and will raise a fatal error unless we provide it with a
+ // /dev/urandom FD beforehand.
+ NaClSecureRngModuleSetUrandomFd(dup(private_interface_->UrandomFD()));
#endif
- // In the plugin, we don't need high resolution time of day.
- NaClAllowLowResolutionTimeOfDay();
- NaClNrdAllModulesInit();
- NaClSrpcModuleInit();
+ // In the plugin, we don't need high resolution time of day.
+ NaClAllowLowResolutionTimeOfDay();
+ NaClNrdAllModulesInit();
+ NaClSrpcModuleInit();
#if NACL_WINDOWS
- NaClSetBrokerDuplicateHandleFunc(private_interface_->BrokerDuplicateHandle);
+ NaClSetBrokerDuplicateHandleFunc(private_interface_->BrokerDuplicateHandle);
#endif
- init_was_successful_ = true;
- return true;
- }
+ init_was_successful_ = true;
+ return true;
+}
- virtual pp::Instance* CreateInstance(PP_Instance pp_instance) {
- MODULE_PRINTF(("ModulePpapi::CreateInstance (pp_instance=%" NACL_PRId32
- ")\n",
- pp_instance));
- Plugin* plugin = Plugin::New(pp_instance);
- MODULE_PRINTF(("ModulePpapi::CreateInstance (return %p)\n",
- static_cast<void* >(plugin)));
- return plugin;
+pp::Instance* ModulePpapi::CreateInstance(PP_Instance pp_instance) {
+ MODULE_PRINTF(("ModulePpapi::CreateInstance (pp_instance=%" NACL_PRId32
+ ")\n",
+ pp_instance));
+ Plugin* plugin = Plugin::New(pp_instance);
+ MODULE_PRINTF(("ModulePpapi::CreateInstance (return %p)\n",
+ static_cast<void* >(plugin)));
+ return plugin;
+}
+
+const uint64_t kMaxCrashesPerInterval = 3;
+const uint64_t kCrashesIntervalInSeconds = 120;
+
+void ModulePpapi::RegisterPluginCrash() {
+ PLUGIN_PRINTF(("ModulePpapi::RegisterPluginCrash ()\n"));
+ if (crash_times_.size() == kMaxCrashesPerInterval) {
+ crash_times_.pop_front();
}
+ int64_t time = NaClGetTimeOfDayMicroseconds();
+ crash_times_.push_back(time);
+}
- private:
- bool init_was_successful_;
- const PPB_NaCl_Private* private_interface_;
-};
+bool ModulePpapi::IsPluginUnstable() {
+ PLUGIN_PRINTF(("ModulePpapi::IsPluginUnstable ()\n"));
+ if (crash_times_.size() != kMaxCrashesPerInterval) {
+ return false;
+ }
+ int64_t now = NaClGetTimeOfDayMicroseconds();
+ int64_t delta = now - crash_times_.front();
+ return delta / (1000.0 * 1000.0) <= kCrashesIntervalInSeconds;
+}
} // namespace plugin
diff --git a/ppapi/native_client/src/trusted/plugin/module_ppapi.h b/ppapi/native_client/src/trusted/plugin/module_ppapi.h
new file mode 100644
index 0000000..b2e7564
--- /dev/null
+++ b/ppapi/native_client/src/trusted/plugin/module_ppapi.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013 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 <deque>
+
+#include "ppapi/c/private/ppb_nacl_private.h"
+#include "ppapi/cpp/module.h"
+
+namespace plugin {
+
+class ModulePpapi : public pp::Module {
+ public:
+ ModulePpapi();
+
+ virtual ~ModulePpapi();
+
+ virtual bool Init();
+
+ virtual pp::Instance* CreateInstance(PP_Instance pp_instance);
+
+ // NaCl crash throttling. If RegisterPluginCrash is called too many times
+ // within a time period, IsPluginUnstable reports true. As long as
+ // IsPluginUnstable returns true, NaCl modules will fail to load.
+ void RegisterPluginCrash();
+ bool IsPluginUnstable();
+
+ private:
+ bool init_was_successful_;
+ const PPB_NaCl_Private* private_interface_;
+
+ // Crash throttling support.
+ std::deque<int64_t> crash_times_;
+};
+
+} // namespace plugin
+
+
+namespace pp {
+
+Module* CreateModule();
+
+} // namespace pp
diff --git a/ppapi/native_client/src/trusted/plugin/plugin.cc b/ppapi/native_client/src/trusted/plugin/plugin.cc
index 5cbb9d7..a4833ee 100644
--- a/ppapi/native_client/src/trusted/plugin/plugin.cc
+++ b/ppapi/native_client/src/trusted/plugin/plugin.cc
@@ -55,6 +55,7 @@
#include "ppapi/native_client/src/trusted/plugin/file_utils.h"
#include "ppapi/native_client/src/trusted/plugin/json_manifest.h"
+#include "ppapi/native_client/src/trusted/plugin/module_ppapi.h"
#include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h"
#include "ppapi/native_client/src/trusted/plugin/nacl_subprocess.h"
#include "ppapi/native_client/src/trusted/plugin/nexe_arch.h"
@@ -1009,6 +1010,10 @@ void Plugin::NexeDidCrash(int32_t pp_error) {
// invocation will just be a no-op, since all the crash log will
// have been received and we'll just get an EOF indication.
CopyCrashLogToJsConsole();
+
+ // Remember the nexe crash time, which helps determine the need to throttle.
+ ModulePpapi* module_ppapi = static_cast<ModulePpapi*>(pp::Module::Get());
+ module_ppapi->RegisterPluginCrash();
}
void Plugin::BitcodeDidTranslate(int32_t pp_error) {
@@ -1204,15 +1209,25 @@ void Plugin::ProcessNaClManifest(const nacl::string& manifest_json) {
EnqueueProgressEvent(kProgressEventProgress);
if (pnacl_options.translate()) {
if (this->nacl_interface()->IsPnaclEnabled()) {
- pp::CompletionCallback translate_callback =
- callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate);
- // Will always call the callback on success or failure.
- pnacl_coordinator_.reset(
- PnaclCoordinator::BitcodeToNative(this,
- program_url,
- pnacl_options,
- translate_callback));
- return;
+ // Check whether PNaCl has been crashing "frequently". If so, report
+ // a load error.
+ ModulePpapi* module_ppapi =
+ static_cast<ModulePpapi*>(pp::Module::Get());
+ if (module_ppapi->IsPluginUnstable()) {
+ error_info.SetReport(ERROR_PNACL_CRASH_THROTTLED,
+ "PNaCl has been temporarily disabled because too"
+ " many crashes have been observed.");
+ } else {
+ pp::CompletionCallback translate_callback =
+ callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate);
+ // Will always call the callback on success or failure.
+ pnacl_coordinator_.reset(
+ PnaclCoordinator::BitcodeToNative(this,
+ program_url,
+ pnacl_options,
+ translate_callback));
+ return;
+ }
} else {
error_info.SetReport(ERROR_PNACL_NOT_ENABLED,
"PNaCl has been disabled (e.g., by setting "
diff --git a/ppapi/native_client/src/trusted/plugin/plugin_error.h b/ppapi/native_client/src/trusted/plugin/plugin_error.h
index b5eb4d8..ac3fbf4 100644
--- a/ppapi/native_client/src/trusted/plugin/plugin_error.h
+++ b/ppapi/native_client/src/trusted/plugin/plugin_error.h
@@ -96,6 +96,7 @@ enum PluginErrorCode {
ERROR_PNACL_NOT_ENABLED = 68,
ERROR_MANIFEST_NOACCESS_URL = 69,
ERROR_NEXE_NOACCESS_URL = 70,
+ ERROR_PNACL_CRASH_THROTTLED = 71,
// If you add a code, read the enum comment above on how to update histograms.
ERROR_MAX
};