Bug 1337290 - 2. Clear cache dir if loading libs failed; r=snorp
authorJim Chen <nchen@mozilla.com>
Wed, 15 Feb 2017 17:12:56 -0500
changeset 343050 e0daea02c01fda3ec2a6ebbfc1fc11c8843c53c3
parent 343049 a792d73dc3454fb61f75cce5ae9f340da5a07868
child 343051 c80d17b6ea4897766816f0f3ac9b005ce551cbd3
push id87038
push usernchen@mozilla.com
push dateWed, 15 Feb 2017 22:13:34 +0000
treeherdermozilla-inbound@427fd5767291 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1337290
milestone54.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
Bug 1337290 - 2. Clear cache dir if loading libs failed; r=snorp If Gecko libs failed to load the first time, clear the cache dir and try again. Only crash if we fail to load the libs a second time.
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/FileUtils.java
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.annotation.RobocopTarget;
 import org.mozilla.gecko.annotation.WrapForJNI;
 import org.mozilla.gecko.mozglue.GeckoLoader;
+import org.mozilla.gecko.util.FileUtils;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -20,16 +21,17 @@ import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.Log;
 
 import java.io.File;
+import java.io.FilenameFilter;
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Locale;
 import java.util.Queue;
 import java.util.concurrent.ConcurrentLinkedQueue;
@@ -384,16 +386,22 @@ public class GeckoThread extends Thread 
             QUEUED_CALLS.trimToSize();
         } else if (lastSkipped < QUEUED_CALLS.size() - 1) {
             // We skipped some; free up null entries at the end,
             // but keep all the previous entries for later.
             QUEUED_CALLS.subList(lastSkipped + 1, QUEUED_CALLS.size()).clear();
         }
     }
 
+    private static void loadGeckoLibs(final Context context, final String resourcePath) {
+        GeckoLoader.loadSQLiteLibs(context, resourcePath);
+        GeckoLoader.loadNSSLibs(context, resourcePath);
+        GeckoLoader.loadGeckoLibs(context, resourcePath);
+    }
+
     private static String initGeckoEnvironment() {
         final Context context = GeckoAppShell.getApplicationContext();
         GeckoLoader.loadMozGlue(context);
         setState(State.MOZGLUE_READY);
 
         final Locale locale = Locale.getDefault();
         final Resources res = context.getResources();
         if (locale.toString().equalsIgnoreCase("zh_hk")) {
@@ -409,21 +417,31 @@ public class GeckoThread extends Thread 
             pluginDirs = GeckoAppShell.getPluginDirectories();
         } catch (Exception e) {
             Log.w(LOGTAG, "Caught exception getting plugin dirs.", e);
         }
 
         final String resourcePath = context.getPackageResourcePath();
         GeckoLoader.setupGeckoEnvironment(context, pluginDirs, context.getFilesDir().getPath());
 
-        GeckoLoader.loadSQLiteLibs(context, resourcePath);
-        GeckoLoader.loadNSSLibs(context, resourcePath);
-        GeckoLoader.loadGeckoLibs(context, resourcePath);
+        try {
+            loadGeckoLibs(context, resourcePath);
+
+        } catch (final Exception e) {
+            // Cannot load libs; try clearing the cached files.
+            Log.w(LOGTAG, "Clearing cache after load libs exception", e);
+            FileUtils.delTree(GeckoLoader.getCacheDir(context),
+                              new FileUtils.FilenameRegexFilter(".*\\.so(?:\\.crc)?$"),
+                              /* recurse */ true);
+
+            // Then try loading again. If this throws again, we actually crash.
+            loadGeckoLibs(context, resourcePath);
+        }
+
         setState(State.LIBS_READY);
-
         return resourcePath;
     }
 
     private void addCustomProfileArg(String args, ArrayList<String> list) {
         // Make sure a profile exists.
         final GeckoProfile profile = getProfile();
         profile.getDir(); // call the lazy initializer
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/FileUtils.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/FileUtils.java
@@ -226,16 +226,20 @@ public class FileUtils {
         // by caching the returned matcher and calling `Matcher.reset` on it. Since Matcher's are not thread safe,
         // this assumes `FilenameFilter.accept` is not run in parallel (which, according to the source, it is not).
         private Matcher mCachedMatcher;
 
         public FilenameRegexFilter(final Pattern pattern) {
             mPattern = pattern;
         }
 
+        public FilenameRegexFilter(final String pattern) {
+            mPattern = Pattern.compile(pattern);
+        }
+
         @Override
         public boolean accept(final File dir, final String filename) {
             if (mCachedMatcher == null) {
                 mCachedMatcher = mPattern.matcher(filename);
             } else {
                 mCachedMatcher.reset(filename);
             }
             return mCachedMatcher.matches();