aboutsummaryrefslogblamecommitdiff
path: root/www/waterfox/files/patch-bug1410457
blob: a9d6511bfc0353ea69ae0e689e6eb78a20e688e5 (plain) (tree)




















































































































                                                                                                                               
commit 1b99cb80da51
Author: Marco Bonardo <mbonardo@mozilla.com>
Date:   Fri Oct 20 17:14:17 2017 +0200

    Bug 1410457 - Places.sqlite may be marked as corrupt if schema migration mixes up sync and async execution. r=Paolo, a=ritu
    
    MozReview-Commit-ID: 7O18MLdHU08
    
    --HG--
    extra : source : c7cab42203dfce68c8c4cd152055a22b4fdbc402
    extra : histedit_source : dbec7034f68805d1597e4577534de934be04af59
---
 toolkit/components/places/Database.cpp | 45 +++++++++++++++++++++++++++++-----
 toolkit/components/places/Database.h   |  3 +++
 2 files changed, 42 insertions(+), 6 deletions(-)

diff --git toolkit/components/places/Database.cpp toolkit/components/places/Database.cpp
index 85e365ff3d9e..3ff9e0fa2078 100644
--- toolkit/components/places/Database.cpp
+++ toolkit/components/places/Database.cpp
@@ -370,6 +370,7 @@ Database::Database()
   , mDBPageSize(0)
   , mDatabaseStatus(nsINavHistoryService::DATABASE_STATUS_OK)
   , mClosed(false)
+  , mShouldConvertIconPayloads(false)
   , mClientsShutdown(new ClientsShutdownBlocker())
   , mConnectionShutdown(new ConnectionShutdownBlocker(this))
   , mMaxUrlLength(0)
@@ -588,13 +589,31 @@ Database::EnsureConnection()
     bool databaseMigrated = false;
     rv = SetupDatabaseConnection(storage);
     if (NS_SUCCEEDED(rv)) {
-      // Failing to initialize the schema always indicates a corruption.
-      if (NS_FAILED(InitSchema(&databaseMigrated))) {
-        rv = NS_ERROR_FILE_CORRUPTED;
+      // Failing to initialize the schema may indicate a corruption.
+      rv = InitSchema(&databaseMigrated);
+      if (NS_FAILED(rv)) {
+        if (rv == NS_ERROR_STORAGE_BUSY ||
+            rv == NS_ERROR_FILE_IS_LOCKED ||
+            rv == NS_ERROR_FILE_NO_DEVICE_SPACE ||
+            rv == NS_ERROR_OUT_OF_MEMORY) {
+          // The database is not corrupt, though some migration step failed.
+          // This may be caused by concurrent use of sync and async Storage APIs
+          // or by a system issue.
+          // The best we can do is trying again. If it should still fail, Places
+          // won't work properly and will be handled as LOCKED.
+          rv = InitSchema(&databaseMigrated);
+          if (NS_FAILED(rv)) {
+            rv = NS_ERROR_FILE_IS_LOCKED;
+          }
+        } else {
+          rv = NS_ERROR_FILE_CORRUPTED;
+        }
       }
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      mDatabaseStatus = nsINavHistoryService::DATABASE_STATUS_CORRUPT;
+      if (rv != NS_ERROR_FILE_IS_LOCKED) {
+        mDatabaseStatus = nsINavHistoryService::DATABASE_STATUS_CORRUPT;
+      }
       // Some errors may not indicate a database corruption, for those cases we
       // just bail out without throwing away a possibly valid places.sqlite.
       if (rv == NS_ERROR_FILE_CORRUPTED) {
@@ -961,6 +980,14 @@ Database::InitSchema(bool* aDatabaseMigrated)
         return NS_ERROR_FILE_CORRUPTED;
       }
 
+      auto guard = MakeScopeExit([&]() {
+        // This runs at the end of the migration, regardless of its success.
+        if (mShouldConvertIconPayloads) {
+          mShouldConvertIconPayloads = false;
+          nsFaviconService::ConvertUnsupportedPayloads(mMainConn);
+        }
+      });
+
       // Firefox 4 uses schema version 11.
 
       // Firefox 8 uses schema version 12.
@@ -1122,6 +1149,11 @@ Database::InitSchema(bool* aDatabaseMigrated)
       // Firefox 57 uses schema version 39.
 
       // Schema Upgrades must add migration code here.
+      // >>> IMPORTANT! <<<
+      // NEVER MIX UP SYNC AND ASYNC EXECUTION IN MIGRATORS, YOU MAY LOCK THE
+      // CONNECTION AND CAUSE FURTHER STEPS TO FAIL.
+      // In case, set a bool and do the async work in the ScopeExit guard just
+      // before the migration steps.
 
       rv = UpdateBookmarkRootTitles();
       // We don't want a broken localization to cause us to think
@@ -2304,8 +2336,9 @@ Database::MigrateV37Up() {
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Start the async conversion
-  nsFaviconService::ConvertUnsupportedPayloads(mMainConn);
+  // The async favicons conversion will happen at the end of the normal schema
+  // migration.
+  mShouldConvertIconPayloads = true;
 
   return NS_OK;
 }
diff --git toolkit/components/places/Database.h toolkit/components/places/Database.h
index 9000fb269dc2..6213678b3e47 100644
--- toolkit/components/places/Database.h
+++ toolkit/components/places/Database.h
@@ -333,6 +333,9 @@ private:
   int32_t mDBPageSize;
   uint16_t mDatabaseStatus;
   bool mClosed;
+  // Used to track whether icon payloads should be converted at the end of
+  // schema migration.
+  bool mShouldConvertIconPayloads;
 
   /**
    * Phases for shutting down the Database.