Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(846)

Unified Diff: base/android/java/src/org/chromium/base/library_loader/Linker.java

Issue 1101473006: Prep for passing fallback descriptor between browser and child processes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase from master. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | content/public/android/java/src/org/chromium/content/app/ChildProcessService.java » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/android/java/src/org/chromium/base/library_loader/Linker.java
diff --git a/base/android/java/src/org/chromium/base/library_loader/Linker.java b/base/android/java/src/org/chromium/base/library_loader/Linker.java
index 7e5099875a6d9be9b438c2e117e3ec7bdc2073b3..49acead1e0aca1676070eb598d6e78538075d4e9 100644
--- a/base/android/java/src/org/chromium/base/library_loader/Linker.java
+++ b/base/android/java/src/org/chromium/base/library_loader/Linker.java
@@ -106,16 +106,14 @@ import javax.annotation.Nullable;
* running any native code from any of the libraries (except their static
* constructors, which can't be avoided).
*
- * - A service process shall call either initServiceProcess() or
- * disableSharedRelros() early (i.e. before any loadLibrary() call).
- * Otherwise, the linker considers that it is running inside the browser
- * process. This is because various Chromium projects have vastly
- * different initialization paths.
+ * - A service process shall call initServiceProcess() early (i.e. before any
+ * loadLibrary() call). Otherwise, the linker considers that it is running
+ * inside the browser process. This is because various Chromium projects have
+ * vastly different initialization paths.
*
- * disableSharedRelros() completely disables shared RELROs, and loadLibrary()
- * will behave exactly like System.loadLibrary().
+ * disableSharedRelros() completely disables shared RELROs.
*
- * initServiceProcess(baseLoadAddress) indicates that shared RELROs are to be
+ * enableSharedRelros(baseLoadAddress) indicates that shared RELROs are to be
* used in this process.
*
* - The browser is in charge of deciding where in memory each library should
@@ -140,18 +138,22 @@ import javax.annotation.Nullable;
* fixed addresses too.
*
* - Once all libraries are loaded in the browser process, one can call
- * getSharedRelros() which returns a Bundle instance containing a map that
- * links each loaded library to its shared RELRO region.
+ * produceSharedStateBundle() which returns a Bundle instance of
+ * resources that a browser process can pass on to child processes. These resources
+ * include a map that links each loaded library to its shared RELRO region.
+ * TODO(oth): include fallback library descriptors.
*
* This Bundle must be passed to each service process, for example through
* a Binder call (note that the Bundle includes file descriptors and cannot
* be added as an Intent extra).
*
- * - In a service process, finishLibraryLoad() will block until the RELRO
- * section Bundle is received. This is typically done by calling
- * useSharedRelros() from another thread.
+ * - In a service process, finishLibraryLoad() will block until the Bundle is received.
+ * When the Bundle is received, the service process must call
+ * consumeSharedStateBundle() from the receiving thread. Typically this will
+ * be a different thread to the thread calling finishLibraryLoad() as it will block
+ * until consumeSharedStateBundle() is called.
*
- * This method also ensures the process uses the shared RELROs.
+ * consumeSharedStateBundle() also ensures the process uses the shared RELROs.
*/
public class Linker {
@@ -197,14 +199,8 @@ public class Linker {
private static boolean sRelroSharingSupported = false;
// Set to true if this runs in the browser process. Disabled by initServiceProcess().
- // TODO(petrcermak): This flag can be incorrectly set to false (even though this might run in
- // the browser process) on low-memory devices.
private static boolean sInBrowserProcess = true;
- // Becomes true to indicate this process needs to wait for a shared RELRO in
- // finishLibraryLoad().
- private static boolean sWaitForSharedRelros = false;
-
// Becomes true when initialization determines that the browser process can use the
// shared RELRO.
private static boolean sBrowserUsesSharedRelro = false;
@@ -274,7 +270,6 @@ public class Linker {
if (!sRelroSharingSupported) {
// Sanity.
sBrowserUsesSharedRelro = false;
- sWaitForSharedRelros = false;
}
sInitialized = true;
@@ -413,18 +408,18 @@ public class Linker {
/**
* Call this method just after loading all native shared libraries in this process.
* Note that when in a service process, this will block until the RELRO bundle is
- * received, i.e. when another thread calls useSharedRelros().
+ * received, i.e. when another thread calls consumeSharedStateBundle().
*/
public static void finishLibraryLoad() {
if (DEBUG) Log.i(TAG, "finishLibraryLoad() called");
synchronized (Linker.class) {
- if (DEBUG) Log.i(TAG, String.format(
- Locale.US,
- "sInBrowserProcess=%s sBrowserUsesSharedRelro=%s sWaitForSharedRelros=%s",
- sInBrowserProcess ? "true" : "false",
- sBrowserUsesSharedRelro ? "true" : "false",
- sWaitForSharedRelros ? "true" : "false"));
-
+ if (DEBUG) {
+ Log.i(TAG,
+ String.format(Locale.US,
+ "sInBrowserProcess=%s sBrowserUsesSharedRelro=%s",
+ sInBrowserProcess ? "true" : "false",
+ sBrowserUsesSharedRelro ? "true" : "false"));
+ }
if (sLoadedLibraries == null) {
if (DEBUG) Log.i(TAG, "No libraries loaded");
} else {
@@ -440,23 +435,13 @@ public class Linker {
if (sBrowserUsesSharedRelro) {
useSharedRelrosLocked(sSharedRelros);
}
- }
-
- if (sWaitForSharedRelros) {
- assert !sInBrowserProcess;
-
- // Wait until the shared relro bundle is received from useSharedRelros().
- while (sSharedRelros == null) {
- try {
- Linker.class.wait();
- } catch (InterruptedException ie) {
- // no-op
- }
+ } else {
+ waitForSharedStateBundleLocked();
+ if (!sSharedRelros.isEmpty()) {
+ useSharedRelrosLocked(sSharedRelros);
+ // Clear the Bundle to ensure it can't be reused.
+ sSharedRelros.clear();
}
- useSharedRelrosLocked(sSharedRelros);
- // Clear the Bundle to ensure its file descriptor references can't be reused.
- sSharedRelros.clear();
- sSharedRelros = null;
}
}
@@ -487,14 +472,15 @@ public class Linker {
}
/**
- * Call this to send a Bundle containing the shared RELRO sections to be
- * used in this process. If initServiceProcess() was previously called,
- * finishLibraryLoad() will not exit until this method is called in another
+ * Call this in service processes to consume shared linker resources in a Bundle from a browser
+ * (these will have been produced with produceSharedStateBundle). If enableSharedRelros() was
+ * previously called, finishLibraryLoad() will not exit until this method is called in another
* thread with a non-null value.
* @param bundle The Bundle instance containing a map of shared RELRO sections
* to use in this process.
*/
- public static void useSharedRelros(Bundle bundle) {
+ public static void consumeSharedStateBundle(Bundle bundle) {
+ assert !sInBrowserProcess : "Browser does not consume shared state bundle.";
// Ensure the bundle uses the application's class loader, not the framework
// one which doesn't know anything about LibInfo.
// Also, hold a fresh copy of it so the caller can't recycle it.
@@ -509,31 +495,43 @@ public class Linker {
parcel.recycle();
}
if (DEBUG) {
- Log.i(TAG, "useSharedRelros() called with " + bundle
- + ", cloned " + clonedBundle);
+ Log.i(TAG, "consumeSharedStateBundle() called with " + bundle + ", cloned "
+ + clonedBundle);
}
synchronized (Linker.class) {
// Note that in certain cases, this can be called before
- // initServiceProcess() in service processes.
+ // enableSharedRelros() in service processes.
sSharedRelros = clonedBundle;
// Tell any listener blocked in finishLibraryLoad() about it.
Linker.class.notifyAll();
}
}
+ private static void waitForSharedStateBundleLocked() {
+ assert Thread.holdsLock(Linker.class);
+
+ while (sSharedRelros == null) {
+ try {
+ Linker.class.wait();
+ } catch (InterruptedException ie) {
+ // no-op
+ }
+ }
+ }
+
/**
- * Call this to retrieve the shared RELRO sections created in this process,
- * after loading all libraries.
- * @return a new Bundle instance, or null if RELRO sharing is disabled on
- * this system, or if initServiceProcess() was called previously.
+ * Call this to retrieve shared state between the browser process and it's
+ * children, e.g. the RELRO sections created in this process.
+ *
+ * Only valid for browser processes and after loading all libraries.
+ *
+ * @return Bundle instance for sharable linker state.
*/
- public static Bundle getSharedRelros() {
- if (DEBUG) Log.i(TAG, "getSharedRelros() called");
+ public static Bundle produceSharedStateBundle() {
+ if (DEBUG) Log.i(TAG, "getSharedStateBundle() called");
synchronized (Linker.class) {
- if (!sInBrowserProcess) {
- if (DEBUG) Log.i(TAG, "... returning null Bundle");
- return null;
- }
+ assert sInBrowserProcess : "Non-browser does not share state bundle.";
+ assert sSharedRelros != null : "Bundle not ready.";
// Return the Bundle created in finishLibraryLoad().
if (DEBUG) Log.i(TAG, "... returning " + sSharedRelros);
@@ -541,16 +539,27 @@ public class Linker {
}
}
+ /**
+ * Call this method before enabling/disabling shared RELRO sections to
+ * indicate that this is a service process (i.e. not a browser process).
+ */
+ public static void initServiceProcess() {
+ if (DEBUG) Log.i(TAG, "initServiceProcess() called");
+ synchronized (Linker.class) {
+ assert sSharedRelros == null : "Bundle is initially empty for non-browser.";
+ sInBrowserProcess = false;
+ sBrowserUsesSharedRelro = false;
+ }
+ }
/**
* Call this method before loading any libraries to indicate that this
- * process shall neither create or reuse shared RELRO sections.
+ * process shall neither create nor reuse shared RELRO sections.
*/
public static void disableSharedRelros() {
if (DEBUG) Log.i(TAG, "disableSharedRelros() called");
synchronized (Linker.class) {
- sInBrowserProcess = false;
- sWaitForSharedRelros = false;
+ sBaseLoadAddress = 0;
sBrowserUsesSharedRelro = false;
}
}
@@ -558,20 +567,20 @@ public class Linker {
/**
* Call this method before loading any libraries to indicate that this
* process is ready to reuse shared RELRO sections from another one.
- * Typically used when starting service processes.
+ * Typically used when starting service processes. Any calls to this method
+ * must be preceded by initServiceProcess().
* @param baseLoadAddress the base library load address to use.
*/
- public static void initServiceProcess(long baseLoadAddress) {
+ public static void enableSharedRelros(long baseLoadAddress) {
if (DEBUG) {
Log.i(TAG, String.format(
- Locale.US, "initServiceProcess(0x%x) called", baseLoadAddress));
+ Locale.US, "enableSharedRelros(0x%x) called", baseLoadAddress));
}
synchronized (Linker.class) {
+ assert !sInBrowserProcess;
+ assert !sBrowserUsesSharedRelro;
ensureInitializedLocked();
- sInBrowserProcess = false;
- sBrowserUsesSharedRelro = false;
if (sRelroSharingSupported) {
- sWaitForSharedRelros = true;
sBaseLoadAddress = baseLoadAddress;
sCurrentLoadAddress = baseLoadAddress;
}
@@ -612,7 +621,6 @@ public class Linker {
// free address space, so disable RELRO shared / fixed load addresses.
Log.w(TAG, "Disabling shared RELROs due address space pressure");
sBrowserUsesSharedRelro = false;
- sWaitForSharedRelros = false;
}
}
}
@@ -730,7 +738,7 @@ public class Linker {
LibInfo libInfo = new LibInfo();
long loadAddress = 0;
- if ((sInBrowserProcess && sBrowserUsesSharedRelro) || sWaitForSharedRelros) {
+ if ((sInBrowserProcess && sBrowserUsesSharedRelro) || sBaseLoadAddress != 0) {
// Load the library at a fixed address.
loadAddress = sCurrentLoadAddress;
}
@@ -1137,7 +1145,7 @@ public class Linker {
// The map of libraries that are currently loaded in this process.
private static HashMap<String, LibInfo> sLoadedLibraries = null;
- // Used to pass the shared RELRO Bundle through Binder.
- public static final String EXTRA_LINKER_SHARED_RELROS =
- "org.chromium.base.android.linker.shared_relros";
+ // Used to pass the shared linker state Bundle through the Binder.
+ public static final String EXTRA_LINKER_SHARED_STATE =
+ "org.chromium.base.android.linker.shared_state";
}
« no previous file with comments | « no previous file | content/public/android/java/src/org/chromium/content/app/ChildProcessService.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698