Bug 1471025: Part 3c - Also pass the shared preference map handle to Android content processes. r=jld
☠☠ backed out by bd747e24063d ☠ ☠
authorKris Maglione <maglione.k@gmail.com>
Fri, 13 Jul 2018 11:06:58 -0700
changeset 426563 38f690f30e78764763bb012045073fa781efa691
parent 426562 4b7a8a35ed956159e2f443c6211164c0cbf3d926
child 426564 83d98ea5ebaccded8a20929c0f3316e5618f1f76
push id34275
push usernerli@mozilla.com
push dateFri, 13 Jul 2018 21:53:18 +0000
treeherdermozilla-central@b79457b703d9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjld
bugs1471025
milestone63.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 1471025: Part 3c - Also pass the shared preference map handle to Android content processes. r=jld MozReview-Commit-ID: CTjDzVC9gcD
dom/ipc/ContentProcess.cpp
dom/ipc/ContentProcess.h
ipc/glue/GeckoChildProcessHost.cpp
mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/process/IChildProcess.aidl
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/GeckoLoader.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoServiceChildProcess.java
mozglue/android/APKOpen.cpp
toolkit/xre/nsEmbedFunctions.cpp
xpcom/build/nsXULAppAPI.h
--- a/dom/ipc/ContentProcess.cpp
+++ b/dom/ipc/ContentProcess.cpp
@@ -78,22 +78,29 @@ SetUpSandboxEnvironment()
   }
 
   SetTmpEnvironmentVariable(sandboxedContentTemp);
 }
 #endif
 
 #ifdef ANDROID
 static int gPrefsFd = -1;
+static int gPrefMapFd = -1;
 
 void
 SetPrefsFd(int aFd)
 {
   gPrefsFd = aFd;
 }
+
+void
+SetPrefMapFd(int aFd)
+{
+  gPrefMapFd = aFd;
+}
 #endif
 
 bool
 ContentProcess::Init(int aArgc, char* aArgv[])
 {
   Maybe<uint64_t> childID;
   Maybe<bool> isForBrowser;
   Maybe<base::SharedMemoryHandle> prefsHandle;
@@ -223,16 +230,19 @@ ContentProcess::Init(int aArgc, char* aA
 #endif /* XP_MACOSX && MOZ_CONTENT_SANDBOX */
     }
   }
 
 #ifdef ANDROID
   // Android is different; get the FD via gPrefsFd instead of a fixed fd.
   MOZ_RELEASE_ASSERT(gPrefsFd != -1);
   prefsHandle = Some(base::FileDescriptor(gPrefsFd, /* auto_close */ true));
+
+  FileDescriptor::UniquePlatformHandle handle(gPrefMapFd);
+  prefMapHandle.emplace(handle.get());
 #elif XP_UNIX
   prefsHandle = Some(base::FileDescriptor(kPrefsFileDescriptor,
                                           /* auto_close */ true));
 
   // The FileDescriptor constructor will clone this handle when constructed,
   // so store it in a UniquePlatformHandle to make sure the original gets
   // closed.
   FileDescriptor::UniquePlatformHandle handle(kPrefMapFileDescriptor);
--- a/dom/ipc/ContentProcess.h
+++ b/dom/ipc/ContentProcess.h
@@ -45,16 +45,18 @@ private:
   // This object initializes and configures COM.
   mozilla::mscom::MainThreadRuntime mCOMRuntime;
 #endif
 
   DISALLOW_EVIL_CONSTRUCTORS(ContentProcess);
 };
 
 #ifdef ANDROID
-// Android doesn't use -prefsHandle, it gets that FD another way.
+// Android doesn't use -prefsHandle or -prefMapHandle. It gets those FDs
+// another way.
 void SetPrefsFd(int aFd);
+void SetPrefMapFd(int aFd);
 #endif
 
 } // namespace dom
 } // namespace mozilla
 
 #endif  // ifndef dom_tabs_ContentThread_h
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -1253,26 +1253,27 @@ GeckoChildProcessHost::LaunchAndroidServ
   }
 
   // XXX: this processing depends entirely on the internals of
   // ContentParent::LaunchSubprocess()
   // GeckoChildProcessHost::PerformAsyncLaunchInternal(), and the order in
   // which they append to fds_to_remap. There must be a better way to do it.
   // See bug 1440207.
   int32_t prefsFd = fds_to_remap[0].first;
-  int32_t ipcFd = fds_to_remap[1].first;
+  int32_t prefMapFd = fds_to_remap[1].first;
+  int32_t ipcFd = fds_to_remap[2].first;
   int32_t crashFd = -1;
   int32_t crashAnnotationFd = -1;
-  if (fds_to_remap.size() == 3) {
-    crashAnnotationFd = fds_to_remap[2].first;
-  }
   if (fds_to_remap.size() == 4) {
-    crashFd = fds_to_remap[2].first;
     crashAnnotationFd = fds_to_remap[3].first;
   }
+  if (fds_to_remap.size() == 5) {
+    crashFd = fds_to_remap[3].first;
+    crashAnnotationFd = fds_to_remap[4].first;
+  }
 
-  int32_t handle = java::GeckoProcessManager::Start(type, jargs, prefsFd, ipcFd, crashFd, crashAnnotationFd);
+  int32_t handle = java::GeckoProcessManager::Start(type, jargs, prefsFd, prefMapFd, ipcFd, crashFd, crashAnnotationFd);
 
   if (process_handle) {
     *process_handle = handle;
   }
 }
 #endif
--- a/mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/process/IChildProcess.aidl
+++ b/mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/process/IChildProcess.aidl
@@ -7,14 +7,15 @@ package org.mozilla.gecko.process;
 import org.mozilla.gecko.process.IProcessManager;
 
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 
 interface IChildProcess {
     int getPid();
     boolean start(in IProcessManager procMan, in String[] args, in Bundle extras, int flags,
-                  in ParcelFileDescriptor prefsPfd, in ParcelFileDescriptor ipcPfd,
+                  in ParcelFileDescriptor prefsPfd, in ParcelFileDescriptor prefMapPfd,
+                  in ParcelFileDescriptor ipcPfd,
                   in ParcelFileDescriptor crashReporterPfd,
                   in ParcelFileDescriptor crashAnnotationPfd);
 
     void crash();
 }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java
@@ -127,16 +127,17 @@ public class GeckoThread extends Thread 
     // Main process parameters
     public static final int FLAG_DEBUGGING = 1 << 0; // Debugging mode.
     public static final int FLAG_PRELOAD_CHILD = 1 << 1; // Preload child during main thread start.
     public static final int FLAG_ENABLE_NATIVE_CRASHREPORTER = 1 << 2; // Enable native crash reporting
     public static final int FLAG_ENABLE_JAVA_CRASHREPORTER = 1 << 3; // Enable java crash reporting
 
     /* package */ static final String EXTRA_ARGS = "args";
     private static final String EXTRA_PREFS_FD = "prefsFd";
+    private static final String EXTRA_PREF_MAP_FD = "prefMapFd";
     private static final String EXTRA_IPC_FD = "ipcFd";
     private static final String EXTRA_CRASH_FD = "crashFd";
     private static final String EXTRA_CRASH_ANNOTATION_FD = "crashAnnotationFd";
 
     private boolean mInitialized;
     private GeckoProfile mProfile;
     private String[] mArgs;
     private Bundle mExtras;
@@ -148,56 +149,60 @@ public class GeckoThread extends Thread 
 
     @WrapForJNI
     private static boolean isChildProcess() {
         return INSTANCE.mExtras.getInt(EXTRA_IPC_FD, -1) != -1;
     }
 
     private synchronized boolean init(final GeckoProfile profile, final String[] args,
                                       final Bundle extras, final int flags,
-                                      final int prefsFd, final int ipcFd,
+                                      final int prefsFd, final int prefMapFd,
+                                      final int ipcFd,
                                       final int crashFd,
                                       final int crashAnnotationFd) {
         ThreadUtils.assertOnUiThread();
         uiThreadId = android.os.Process.myTid();
 
         if (mInitialized) {
             return false;
         }
 
         mProfile = profile;
         mArgs = args;
         mFlags = flags;
 
         mExtras = (extras != null) ? new Bundle(extras) : new Bundle(3);
         mExtras.putInt(EXTRA_PREFS_FD, prefsFd);
+        mExtras.putInt(EXTRA_PREF_MAP_FD, prefMapFd);
         mExtras.putInt(EXTRA_IPC_FD, ipcFd);
         mExtras.putInt(EXTRA_CRASH_FD, crashFd);
         mExtras.putInt(EXTRA_CRASH_ANNOTATION_FD, crashAnnotationFd);
 
         mInitialized = true;
         notifyAll();
         return true;
     }
 
     public static boolean initMainProcess(final GeckoProfile profile, final String[] args,
                                           final Bundle extras, final int flags) {
         return INSTANCE.init(profile, args, extras, flags, /* fd */ -1,
-                             /* fd */ -1, /* fd */ -1, /* fd */ -1);
+                             /* fd */ -1, /* fd */ -1, /* fd */ -1,
+                             /* fd */ -1);
     }
 
     public static boolean initChildProcess(final String[] args,
                                            final Bundle extras,
                                            final int flags,
                                            final int prefsFd,
+                                           final int prefMapFd,
                                            final int ipcFd,
                                            final int crashFd,
                                            final int crashAnnotationFd) {
         return INSTANCE.init(/* profile */ null, args, extras, flags,
-                             prefsFd, ipcFd, crashFd, crashAnnotationFd);
+                             prefsFd, prefMapFd, ipcFd, crashFd, crashAnnotationFd);
     }
 
     private static boolean canUseProfile(final Context context, final GeckoProfile profile,
                                          final String profileName, final File profileDir) {
         if (profileDir != null && !profileDir.isDirectory()) {
             return false;
         }
 
@@ -492,16 +497,17 @@ public class GeckoThread extends Thread 
             GeckoAppShell.ensureCrashHandling();
         }
 
         GeckoLoader.setupGeckoEnvironment(context, context.getFilesDir().getPath(), env);
 
         // And go.
         GeckoLoader.nativeRun(args,
                               mExtras.getInt(EXTRA_PREFS_FD, -1),
+                              mExtras.getInt(EXTRA_PREF_MAP_FD, -1),
                               mExtras.getInt(EXTRA_IPC_FD, -1),
                               mExtras.getInt(EXTRA_CRASH_FD, -1),
                               mExtras.getInt(EXTRA_CRASH_ANNOTATION_FD, -1));
 
         // And... we're done.
         final boolean restarting = isState(State.RESTARTING);
         setState(State.EXITED);
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/GeckoLoader.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/GeckoLoader.java
@@ -451,15 +451,15 @@ public final class GeckoLoader {
         }
     }
 
     // These methods are implemented in mozglue/android/nsGeckoUtils.cpp
     private static native void putenv(String map);
     public static native boolean verifyCRCs(String apkName);
 
     // These methods are implemented in mozglue/android/APKOpen.cpp
-    public static native void nativeRun(String[] args, int prefsFd, int ipcFd, int crashFd, int crashAnnotationFd);
+    public static native void nativeRun(String[] args, int prefsFd, int prefMapFd, int ipcFd, int crashFd, int crashAnnotationFd);
     private static native void loadGeckoLibsNative(String apkName);
     private static native void loadSQLiteLibsNative(String apkName);
     private static native void loadNSSLibsNative(String apkName);
     public static native boolean neonCompatible();
     public static native void suppressCrashDialog();
 }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.java
@@ -177,67 +177,71 @@ public final class GeckoProcessManager e
         try {
             mConnections.get("tab").bind().crash();
         } catch (RemoteException e) {
         }
     }
 
     @WrapForJNI
     private static int start(final String type, final String[] args,
-                             final int prefsFd, final int ipcFd,
+                             final int prefsFd, final int prefMapFd,
+                             final int ipcFd,
                              final int crashFd, final int crashAnnotationFd) {
-        return INSTANCE.start(type, args, prefsFd, ipcFd, crashFd, crashAnnotationFd, /* retry */ false);
+        return INSTANCE.start(type, args, prefsFd, prefMapFd, ipcFd, crashFd, crashAnnotationFd, /* retry */ false);
     }
 
     private int filterFlagsForChild(int flags) {
         return flags & (GeckoThread.FLAG_ENABLE_JAVA_CRASHREPORTER |
                 GeckoThread.FLAG_ENABLE_NATIVE_CRASHREPORTER);
     }
 
-    private int start(final String type, final String[] args, final int prefsFd,
+    private int start(final String type, final String[] args,
+                      final int prefsFd, final int prefMapFd,
                       final int ipcFd, final int crashFd,
                       final int crashAnnotationFd, final boolean retry) {
         final ChildConnection connection = getConnection(type);
         final IChildProcess child = connection.bind();
         if (child == null) {
             return 0;
         }
 
         final Bundle extras = GeckoThread.getActiveExtras();
         final ParcelFileDescriptor prefsPfd;
+        final ParcelFileDescriptor prefMapPfd;
         final ParcelFileDescriptor ipcPfd;
         final ParcelFileDescriptor crashPfd;
         final ParcelFileDescriptor crashAnnotationPfd;
         try {
             prefsPfd = ParcelFileDescriptor.fromFd(prefsFd);
+            prefMapPfd = ParcelFileDescriptor.fromFd(prefMapFd);
             ipcPfd = ParcelFileDescriptor.fromFd(ipcFd);
             crashPfd = (crashFd >= 0) ? ParcelFileDescriptor.fromFd(crashFd) : null;
             crashAnnotationPfd = (crashAnnotationFd >= 0) ? ParcelFileDescriptor.fromFd(crashAnnotationFd) : null;
         } catch (final IOException e) {
             Log.e(LOGTAG, "Cannot create fd for " + type, e);
             return 0;
         }
 
         final int flags = filterFlagsForChild(GeckoThread.getActiveFlags());
 
         boolean started = false;
         try {
-            started = child.start(this, args, extras, flags, prefsPfd, ipcPfd, crashPfd,
-                                  crashAnnotationPfd);
+            started = child.start(this, args, extras, flags, prefsPfd, prefMapPfd,
+                                  ipcPfd, crashPfd, crashAnnotationPfd);
         } catch (final RemoteException e) {
         }
 
         if (!started) {
             if (retry) {
                 Log.e(LOGTAG, "Cannot restart child " + type);
                 return 0;
             }
             Log.w(LOGTAG, "Attempting to kill running child " + type);
             connection.unbind();
-            return start(type, args, prefsFd, ipcFd, crashFd, crashAnnotationFd, /* retry */ true);
+            return start(type, args, prefsFd, prefMapFd, ipcFd, crashFd, crashAnnotationFd, /* retry */ true);
         }
 
         try {
             if (crashAnnotationPfd != null) {
                 crashAnnotationPfd.close();
             }
             if (crashPfd != null) {
                 crashPfd.close();
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoServiceChildProcess.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoServiceChildProcess.java
@@ -57,39 +57,41 @@ public class GeckoServiceChildProcess ex
         }
 
         @Override
         public boolean start(final IProcessManager procMan,
                              final String[] args,
                              final Bundle extras,
                              final int flags,
                              final ParcelFileDescriptor prefsPfd,
+                             final ParcelFileDescriptor prefMapPfd,
                              final ParcelFileDescriptor ipcPfd,
                              final ParcelFileDescriptor crashReporterPfd,
                              final ParcelFileDescriptor crashAnnotationPfd) {
             synchronized (GeckoServiceChildProcess.class) {
                 if (sProcessManager != null) {
                     Log.e(LOGTAG, "Child process already started");
                     return false;
                 }
                 sProcessManager = procMan;
             }
 
             final int prefsFd = prefsPfd.detachFd();
+            final int prefMapFd = prefMapPfd.detachFd();
             final int ipcFd = ipcPfd.detachFd();
             final int crashReporterFd = crashReporterPfd != null ?
                                         crashReporterPfd.detachFd() : -1;
             final int crashAnnotationFd = crashAnnotationPfd != null ?
                                           crashAnnotationPfd.detachFd() : -1;
 
             ThreadUtils.postToUiThread(new Runnable() {
                 @Override
                 public void run() {
-                    if (GeckoThread.initChildProcess(args, extras, flags, prefsFd, ipcFd, crashReporterFd,
-                                                     crashAnnotationFd)) {
+                    if (GeckoThread.initChildProcess(args, extras, flags, prefsFd, prefMapFd, ipcFd,
+                                                     crashReporterFd, crashAnnotationFd)) {
                         GeckoThread.launch();
                     }
                 }
             });
             return true;
         }
 
         @Override
--- a/mozglue/android/APKOpen.cpp
+++ b/mozglue/android/APKOpen.cpp
@@ -388,32 +388,32 @@ FreeArgv(char** argv, int argc)
   for (int ix=0; ix < argc; ix++) {
     // String was allocated with strndup, so need to use free to deallocate.
     free(argv[ix]);
   }
   delete[](argv);
 }
 
 extern "C" APKOPEN_EXPORT void MOZ_JNICALL
-Java_org_mozilla_gecko_mozglue_GeckoLoader_nativeRun(JNIEnv *jenv, jclass jc, jobjectArray jargs, int prefsFd, int ipcFd, int crashFd, int crashAnnotationFd)
+Java_org_mozilla_gecko_mozglue_GeckoLoader_nativeRun(JNIEnv *jenv, jclass jc, jobjectArray jargs, int prefsFd, int prefMapFd, int ipcFd, int crashFd, int crashAnnotationFd)
 {
   int argc = 0;
   char** argv = CreateArgvFromObjectArray(jenv, jargs, &argc);
 
   if (ipcFd < 0) {
     if (gBootstrap == nullptr) {
       FreeArgv(argv, argc);
       return;
     }
 
     ElfLoader::Singleton.ExpectShutdown(false);
     gBootstrap->GeckoStart(jenv, argv, argc, sAppData);
     ElfLoader::Singleton.ExpectShutdown(true);
   } else {
-    gBootstrap->XRE_SetAndroidChildFds(jenv, { prefsFd, ipcFd, crashFd, crashAnnotationFd });
+    gBootstrap->XRE_SetAndroidChildFds(jenv, { prefsFd, prefMapFd, ipcFd, crashFd, crashAnnotationFd });
     gBootstrap->XRE_SetProcessType(argv[argc - 1]);
 
     XREChildData childData;
     gBootstrap->XRE_InitChildProcess(argc - 1, argv, &childData);
   }
 
   gBootstrap.reset();
   FreeArgv(argv, argc);
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -243,16 +243,17 @@ GeckoProcessType sChildProcessType = Gec
 } // namespace mozilla
 
 #if defined(MOZ_WIDGET_ANDROID)
 void
 XRE_SetAndroidChildFds (JNIEnv* env, const XRE_AndroidChildFds& fds)
 {
   mozilla::jni::SetGeckoThreadEnv(env);
   mozilla::dom::SetPrefsFd(fds.mPrefsFd);
+  mozilla::dom::SetPrefMapFd(fds.mPrefMapFd);
   IPC::Channel::SetClientChannelFd(fds.mIpcFd);
   CrashReporter::SetNotificationPipeForChild(fds.mCrashFd);
   CrashReporter::SetCrashAnnotationPipeForChild(fds.mCrashAnnotationFd);
 }
 #endif // defined(MOZ_WIDGET_ANDROID)
 
 void
 XRE_SetProcessType(const char* aProcessTypeString)
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -395,16 +395,17 @@ static_assert(MOZ_ARRAY_LENGTH(kGeckoPro
 
 XRE_API(const char*,
         XRE_ChildProcessTypeToString, (GeckoProcessType aProcessType))
 
 #if defined(MOZ_WIDGET_ANDROID)
 struct XRE_AndroidChildFds
 {
   int mPrefsFd;
+  int mPrefMapFd;
   int mIpcFd;
   int mCrashFd;
   int mCrashAnnotationFd;
 };
 
 XRE_API(void,
         XRE_SetAndroidChildFds, (JNIEnv* env, const XRE_AndroidChildFds& fds))
 #endif // defined(MOZ_WIDGET_ANDROID)