Bug 1337290 - 2. Clear cache dir if loading libs failed; r=snorp a=gchang
authorJim Chen <nchen@mozilla.com>
Wed, 15 Feb 2017 17:12:56 -0500
changeset 376416 caa026ea3982058e20ac3af1a6ff0f7ee3f56306
parent 376415 3cc59d37b9f357849d6a484979ca97e901411714
child 376417 f97503c9caea474dcea727954e4ae62f68482e4d
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp, gchang
bugs1337290
milestone53.0a2
Bug 1337290 - 2. Clear cache dir if loading libs failed; r=snorp a=gchang 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
@@ -225,16 +225,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();