Factor prefs out of DriverCrashGuard. (bug 1190281 part 6, r=mattwoodrow)
☠☠ backed out by 70c553b37c19 ☠ ☠
authorDavid Anderson <danderson@mozilla.com>
Tue, 11 Aug 2015 00:29:08 -0700
changeset 291481 7f904a453bdb68e29e3921df61431c46a84f4a71
parent 291480 e17123b5bafd3bbc31c61d47873be59bf3bc9acf
child 291482 c85c1d11bd72f43a69133b2076c6dd3c256d8716
push id962
push userjlund@mozilla.com
push dateFri, 04 Dec 2015 23:28:54 +0000
treeherdermozilla-release@23a2d286e80f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1190281
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Factor prefs out of DriverCrashGuard. (bug 1190281 part 6, r=mattwoodrow)
gfx/src/DriverCrashGuard.cpp
gfx/src/DriverCrashGuard.h
--- a/gfx/src/DriverCrashGuard.cpp
+++ b/gfx/src/DriverCrashGuard.cpp
@@ -15,20 +15,32 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Services.h"
 #include "mozilla/gfx/Logging.h"
 
 namespace mozilla {
 namespace gfx {
 
-DriverCrashGuard::DriverCrashGuard()
- : mInitialized(false)
- , mIsChromeProcess(XRE_GetProcessType() == GeckoProcessType_Default)
+static const size_t NUM_CRASH_GUARD_TYPES = size_t(CrashGuardType::NUM_TYPES);
+static const char* sCrashGuardNames[NUM_CRASH_GUARD_TYPES] = {
+  "d3d11layers",
+};
+
+DriverCrashGuard::DriverCrashGuard(CrashGuardType aType)
+ : mType(aType)
+ , mInitialized(false)
 {
+  MOZ_ASSERT(mType < CrashGuardType::NUM_TYPES);
+
+  mStatusPref.Assign("gfx.driver-init.status.");
+  mStatusPref.Append(sCrashGuardNames[size_t(mType)]);
+
+  mGuardFilename.Assign(sCrashGuardNames[size_t(mType)]);
+  mGuardFilename.Append(".guard");
 }
 
 void
 DriverCrashGuard::InitializeIfNeeded()
 {
   if (mInitialized) {
     return;
   }
@@ -54,24 +66,24 @@ DriverCrashGuard::Initialize()
     // class already updated the environment in this session. Enable the
     // guard.
     AllowDriverInitAttempt();
   }
 }
 
 DriverCrashGuard::~DriverCrashGuard()
 {
-  if (mLockFile) {
-    mLockFile->Remove(false);
+  if (mGuardFile) {
+    mGuardFile->Remove(false);
   }
 
-  if (gfxPrefs::DriverInitStatus() == int32_t(DriverInitStatus::Attempting)) {
+  if (GetStatus() == DriverInitStatus::Attempting) {
     // If we attempted to initialize the driver, and got this far without
     // crashing, assume everything is okay.
-    gfxPrefs::SetDriverInitStatus(int32_t(DriverInitStatus::Okay));
+    SetStatus(DriverInitStatus::Okay);
 
 #ifdef MOZ_CRASHREPORTER
     // Remove the crash report annotation.
     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("GraphicsStartupTest"),
                                        NS_LITERAL_CSTRING(""));
 #endif
   }
 }
@@ -81,66 +93,68 @@ DriverCrashGuard::Crashed()
 {
   InitializeIfNeeded();
   return gfxPrefs::DriverInitStatus() == int32_t(DriverInitStatus::Recovered);
 }
 
 bool
 DriverCrashGuard::InitLockFilePath()
 {
-  NS_GetSpecialDirectory(NS_APP_USER_PROFILE_LOCAL_50_DIR, getter_AddRefs(mLockFile));
-  if (!mLockFile) {
+  NS_GetSpecialDirectory(NS_APP_USER_PROFILE_LOCAL_50_DIR, getter_AddRefs(mGuardFile));
+  if (!mGuardFile) {
     return false;
   }
-  if (!NS_SUCCEEDED(mLockFile->AppendNative(NS_LITERAL_CSTRING("gfxinit.lock")))) {
+
+  if (!NS_SUCCEEDED(mGuardFile->AppendNative(mGuardFilename))) {
     return false;
   }
   return true;
 }
 
 void
 DriverCrashGuard::AllowDriverInitAttempt()
 {
   // Create a temporary tombstone/lockfile.
   FILE* fp;
-  if (!NS_SUCCEEDED(mLockFile->OpenANSIFileDesc("w", &fp))) {
+  if (!NS_SUCCEEDED(mGuardFile->OpenANSIFileDesc("w", &fp))) {
     return;
   }
   fclose(fp);
 
-  gfxPrefs::SetDriverInitStatus(int32_t(DriverInitStatus::Attempting));
+  SetStatus(DriverInitStatus::Attempting);
 
   // Flush preferences, so if we crash, we don't think the environment has changed again.
   FlushPreferences();
 
 #ifdef MOZ_CRASHREPORTER
   CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("GraphicsStartupTest"),
                                      NS_LITERAL_CSTRING("1"));
 #endif
 }
 
 bool
 DriverCrashGuard::RecoverFromDriverInitCrash()
 {
   bool exists;
-  if (mLockFile &&
-      NS_SUCCEEDED(mLockFile->Exists(&exists)) &&
+  if (mGuardFile &&
+      NS_SUCCEEDED(mGuardFile->Exists(&exists)) &&
       exists)
   {
     // If we get here, we've just recovered from a crash. Disable acceleration
     // until the environment changes. Since we may have crashed before
     // preferences we're flushed, we cache the environment again, then flush
     // preferences so child processes can start right away.
-    gfxPrefs::SetDriverInitStatus(int32_t(DriverInitStatus::Recovered));
+    SetStatus(DriverInitStatus::Recovered);
+    UpdateBaseEnvironment();
     UpdateEnvironment();
     FlushPreferences();
     LogCrashRecovery();
     return true;
   }
-  if (gfxPrefs::DriverInitStatus() == int32_t(DriverInitStatus::Recovered)) {
+  if (GetStatus() == DriverInitStatus::Recovered) {
     // If we get here, we crashed in a previous session.
     LogFeatureDisabled();
     return true;
   }
   return false;
 }
 
 // Return true if the caller should proceed to guard for crashes. False if
@@ -174,16 +188,19 @@ DriverCrashGuard::UpdateBaseEnvironment(
     changed |= CheckAndUpdatePref("gfx.driver-init.driverVersion", value);
     mGfxInfo->GetAdapterDeviceID(value);
     changed |= CheckAndUpdatePref("gfx.driver-init.deviceID", value);
   }
 
   // Firefox properties.
   changed |= CheckAndUpdatePref("gfx.driver-init.appVersion", NS_LITERAL_STRING(MOZ_APP_VERSION));
 
+  // Finally, mark as changed if the status has been reset by the user.
+  changed |= (GetStatus() == DriverInitStatus::None);
+
   return changed;
 }
 
 bool
 DriverCrashGuard::FeatureEnabled(int aFeature)
 {
   int32_t status;
   if (!NS_SUCCEEDED(mGfxInfo->GetFeatureStatus(aFeature, &status))) {
@@ -211,32 +228,45 @@ DriverCrashGuard::CheckAndUpdatePref(con
   nsAdoptingString oldValue = Preferences::GetString(aPrefName);
   if (oldValue == aCurrentValue) {
     return false;
   }
   Preferences::SetString(aPrefName, aCurrentValue);
   return true;
 }
 
+DriverInitStatus
+DriverCrashGuard::GetStatus() const
+{
+  return (DriverInitStatus)Preferences::GetInt(mStatusPref.get(), 0);
+}
+
+void
+DriverCrashGuard::SetStatus(DriverInitStatus aStatus)
+{
+  Preferences::SetInt(mStatusPref.get(), int32_t(aStatus));
+}
+
 void
 DriverCrashGuard::FlushPreferences()
 {
   if (nsIPrefService* prefService = Preferences::GetService()) {
     prefService->SavePrefFile(nullptr);
   }
 }
 
 D3D11LayersCrashGuard::D3D11LayersCrashGuard()
+ : DriverCrashGuard(CrashGuardType::D3D11Layers)
 {
 }
 
 void
 D3D11LayersCrashGuard::Initialize()
 {
-  if (!mIsChromeProcess) {
+  if (!XRE_IsParentProcess()) {
     // We assume the parent process already performed crash detection for
     // graphics devices.
     return;
   }
 
   DriverCrashGuard::Initialize();
 
   // If no telemetry states have been recorded, this will set the state to okay.
--- a/gfx/src/DriverCrashGuard.h
+++ b/gfx/src/DriverCrashGuard.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef gfx_src_DriverCrashGuard_h__
 #define gfx_src_DriverCrashGuard_h__
 
 #include "gfxCore.h"
 #include "nsCOMPtr.h"
 #include "nsIGfxInfo.h"
 #include "nsIFile.h"
+#include "nsString.h"
 
 namespace mozilla {
 namespace gfx {
 
 enum class DriverInitStatus
 {
   // Drivers have not been initialized yet.
   None,
@@ -23,68 +24,79 @@ enum class DriverInitStatus
 
   // Drivers were successfully initialized last run.
   Okay,
 
   // We crashed during driver initialization, and have restarted.
   Recovered
 };
 
+enum class CrashGuardType : uint32_t
+{
+  D3D11Layers,
+
+  NUM_TYPES
+};
+
 // DriverCrashGuard is used to detect crashes at graphics driver callsites.
 // 
 // If the graphics environment is unrecognized or has changed since the last
 // session, the crash guard will activate and will detect any crashes within
 // the scope of the guard object.
 //
 // If a callsite has a previously encountered crash, and the environment has
 // not changed since the last session, then the guard will set a status flag
 // indicating that the driver should not be used.
 class DriverCrashGuard
 {
 public:
-  DriverCrashGuard();
+  DriverCrashGuard(CrashGuardType aType);
   ~DriverCrashGuard();
 
   bool Crashed();
 
   // These are the values reported to Telemetry (GRAPHICS_DRIVER_STARTUP_TEST).
   // Values should not change; add new values to the end.
   enum class TelemetryState {
     Okay = 0,
     EnvironmentChanged = 1,
     RecoveredFromCrash = 2,
     FeatureDisabled = 3
   };
 
 protected:
+  virtual void Initialize();
   virtual bool UpdateEnvironment() = 0;
-  virtual void Initialize() = 0;
   virtual void LogCrashRecovery() = 0;
   virtual void LogFeatureDisabled() = 0;
 
   // Helper functions.
   bool FeatureEnabled(int aFeature);
   bool CheckAndUpdatePref(const char* aPrefName, const nsAString& aCurrentValue);
   bool CheckAndUpdateBoolPref(const char* aPrefName, bool aCurrentValue);
 
 private:
   void InitializeIfNeeded();
   bool InitLockFilePath();
   void AllowDriverInitAttempt();
   bool RecoverFromDriverInitCrash();
   void FlushPreferences();
   bool PrepareToGuard();
   bool UpdateBaseEnvironment();
+  DriverInitStatus GetStatus() const;
+  void SetStatus(DriverInitStatus aStatus);
 
 private:
+  CrashGuardType mType;
   bool mInitialized;
-  nsCOMPtr<nsIFile> mLockFile;
+  nsCOMPtr<nsIFile> mGuardFile;
 
 protected:
-  bool mIsChromeProcess;
+  nsCString mStatusPref;
+  nsCString mGuardFilename;
   nsCOMPtr<nsIGfxInfo> mGfxInfo;
 };
 
 class D3D11LayersCrashGuard final : public DriverCrashGuard
 {
  public:
   D3D11LayersCrashGuard();