Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8948c01e authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Yell when calling installd with PM lock held.

As a matter of policy, we should never be holding the mPackages lock
while calling down into installd.  This little bit of logic helps us
catch accidental cases where this happens.

Change-Id: I676c81df43ef936ffd36290d45a79429630c1b4b
parent fafb81b7
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import android.net.LocalSocketAddress;
import android.os.SystemClock;
import android.util.Slog;

import com.android.internal.util.Preconditions;

import libcore.io.IoUtils;
import libcore.io.Streams;

@@ -42,11 +44,22 @@ public class InstallerConnection {
    private OutputStream mOut;
    private LocalSocket mSocket;

    private volatile Object mWarnIfHeld;

    private final byte buf[] = new byte[1024];

    public InstallerConnection() {
    }

    /**
     * Yell loudly if someone tries making future calls while holding a lock on
     * the given object.
     */
    public void setWarnIfHeld(Object warnIfHeld) {
        Preconditions.checkState(mWarnIfHeld == null);
        mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld);
    }

    public synchronized String transact(String cmd) {
        if (!connect()) {
            Slog.e(TAG, "connection failed");
@@ -84,6 +97,11 @@ public class InstallerConnection {
    }

    public int execute(String cmd) {
        if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
            Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
                    + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
        }

        String res = transact(cmd);
        try {
            return Integer.parseInt(res);
+1 −1
Original line number Diff line number Diff line
@@ -1440,7 +1440,7 @@ class MountService extends IMountService.Stub
        mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
                null);
        mConnector.setDebug(true);
        mConnector.setLockWarning(mLock);
        mConnector.setWarnIfHeld(mLock);

        Thread thread = new Thread(mConnector, VOLD_TAG);
        thread.start();
+10 −8
Original line number Diff line number Diff line
@@ -25,10 +25,10 @@ import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.LocalLog;
import android.util.Log;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
import com.google.android.collect.Lists;

import java.io.FileDescriptor;
@@ -58,7 +58,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
    private LocalLog mLocalLog;

    private volatile boolean mDebug = false;
    private volatile Object mLockWarning;
    private volatile Object mWarnIfHeld;

    private final ResponseQueue mResponseQueue;

@@ -110,11 +110,12 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
    }

    /**
     * Yell loudly if someone tries making future {@link #execute(Command)} calls while holding a
     * lock on the given object.
     * Yell loudly if someone tries making future {@link #execute(Command)}
     * calls while holding a lock on the given object.
     */
    public void setLockWarning(Object lockWarning) {
        mLockWarning = lockWarning;
    public void setWarnIfHeld(Object warnIfHeld) {
        Preconditions.checkState(mWarnIfHeld == null);
        mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld);
    }

    @Override
@@ -404,8 +405,9 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
     */
    public NativeDaemonEvent[] executeForList(long timeoutMs, String cmd, Object... args)
            throws NativeDaemonConnectorException {
        if (mLockWarning != null && Thread.holdsLock(mLockWarning)) {
            Log.wtf(TAG, "Calling thread is holding lock " + mLockWarning, new Throwable());
        if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
            Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
                    + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
        }

        final long startTime = SystemClock.elapsedRealtime();
+8 −0
Original line number Diff line number Diff line
@@ -53,6 +53,14 @@ public final class Installer extends SystemService {
        mInstaller = new InstallerConnection();
    }

    /**
     * Yell loudly if someone tries making future calls while holding a lock on
     * the given object.
     */
    public void setWarnIfHeld(Object warnIfHeld) {
        mInstaller.setWarnIfHeld(warnIfHeld);
    }

    @Override
    public void onStart() {
        Slog.i(TAG, "Waiting for installd to be ready.");
+5 −0
Original line number Diff line number Diff line
@@ -2391,6 +2391,11 @@ public class PackageManagerService extends IPackageManager.Stub {
        // tidy.
        Runtime.getRuntime().gc();
        // The initial scanning above does many calls into installd while
        // holding the mPackages lock, but we're mostly interested in yelling
        // once we have a booted system.
        mInstaller.setWarnIfHeld(mPackages);
        // Expose private service for system components to use.
        LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());
    }