From bfee2567d66a043b01936b255bab671ccab15e50 Mon Sep 17 00:00:00 2001 From: Benjamin Smedberg Date: Wed, 21 Jun 2017 11:17:01 -0400 Subject: [PATCH] Bug 1372988 part A - Warn when user prefs are set after the profile is dead, because the prefs won't get saved anyway. r=milan MozReview-Commit-ID: IfwL5yYtLcF --HG-- extra : rebase_source : f03a79b5f7c3b8eb802bfd2db9991e5ed6c74a8f --- modules/libpref/Preferences.cpp | 25 +++++++++++++++++++++---- modules/libpref/Preferences.h | 3 ++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp index fa4f0f7f0278..cd900145bb07 100644 --- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -102,6 +102,9 @@ Preferences::DirtyCallback() } if (gHashTable && sPreferences && !sPreferences->mDirty) { sPreferences->mDirty = true; + + NS_WARNING_ASSERTION(!sPreferences->mProfileShutdown, + "Setting user pref after profile shutdown."); } } @@ -662,7 +665,6 @@ Preferences::Shutdown() */ Preferences::Preferences() - : mDirty(false) { } @@ -796,11 +798,19 @@ Preferences::Observe(nsISupports *aSubject, const char *aTopic, nsresult rv = NS_OK; if (!nsCRT::strcmp(aTopic, "profile-before-change")) { - rv = SavePrefFile(nullptr); - } else if (!nsCRT::strcmp(aTopic, "profile-before-change-telemetry")) { + // Normally prefs aren't written after this point, and so we kick off + // an asynchronous pref save so that I/O can be done in parallel with + // other shutdown. if (AllowOffMainThreadSave()) { - PreferencesWriter::Flush(); + SavePrefFile(nullptr); } + } else if (!nsCRT::strcmp(aTopic, "profile-before-change-telemetry")) { + // It's possible that a profile-before-change observer after ours + // set a pref. A blocking save here re-saves if necessary and also waits + // for any pending saves to complete. + SavePrefFileBlocking(); + MOZ_ASSERT(!mDirty, "Preferences should not be dirty"); + mProfileShutdown = true; } else if (!strcmp(aTopic, "load-extension-defaults")) { pref_LoadPrefsInDirList(NS_EXT_PREFS_DEFAULTS_DIR_LIST); } else if (!nsCRT::strcmp(aTopic, "reload-default-prefs")) { @@ -1154,6 +1164,13 @@ Preferences::SavePrefFileInternal(nsIFile *aFile, SaveMethod aSaveMethod) return NS_OK; } + // check for profile shutdown after mDirty because the runnables from + // DirtyCallback can still be pending + if (mProfileShutdown) { + NS_WARNING("Cannot save pref file after profile shutdown."); + return NS_ERROR_ILLEGAL_DURING_SHUTDOWN; + } + // It's possible that we never got a prefs file. nsresult rv = NS_OK; if (mCurrentFile) { diff --git a/modules/libpref/Preferences.h b/modules/libpref/Preferences.h index 86c65cfee0b3..bef0a15cee90 100644 --- a/modules/libpref/Preferences.h +++ b/modules/libpref/Preferences.h @@ -485,7 +485,8 @@ protected: private: nsCOMPtr mCurrentFile; - bool mDirty; + bool mDirty = false; + bool mProfileShutdown = false; static Preferences* sPreferences; static nsIPrefBranch* sRootBranch;