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

Commit 0791fbf8 authored by Martijn Coenen's avatar Martijn Coenen
Browse files

Don't lose BR_RELEASE/BR_DECREFS commands.

BR_RELEASE/BR_DECREFS commands are stored in mPendingStrongDerefs
and mPendingWeakDerefs, respectively. During processPendingDerefs(),
we actually execute the corresponding decStrong()/decWeak() operations.

The problem is that when we're done, we clear() the mPending vectors
without checking if new entries have been added to them. This can
happen, because decStrong()/decWeak() might cause destructors to run,
which in turn can invoke outgoing transactions that may result in
a BR_RELEASE/BR_DECREFS being queued.

Bug: 63079216
Test: binderLibTest
Change-Id: Ib1deca3f317f8b5068b4b9eddfc4219b9ec87740
parent 3c80f175
Loading
Loading
Loading
Loading
+22 −11
Original line number Diff line number Diff line
@@ -465,22 +465,33 @@ status_t IPCThreadState::getAndExecuteCommand()
void IPCThreadState::processPendingDerefs()
{
    if (mIn.dataPosition() >= mIn.dataSize()) {
        size_t numPending = mPendingWeakDerefs.size();
        if (numPending > 0) {
            for (size_t i = 0; i < numPending; i++) {
                RefBase::weakref_type* refs = mPendingWeakDerefs[i];
        /*
         * The decWeak()/decStrong() calls may cause a destructor to run,
         * which in turn could have initiated an outgoing transaction,
         * which in turn could cause us to add to the pending refs
         * vectors; so instead of simply iterating, loop until they're empty.
         *
         * We do this in an outer loop, because calling decStrong()
         * may result in something being added to mPendingWeakDerefs,
         * which could be delayed until the next incoming command
         * from the driver if we don't process it now.
         */
        while (mPendingWeakDerefs.size() > 0 || mPendingStrongDerefs.size() > 0) {
            while (mPendingWeakDerefs.size() > 0) {
                RefBase::weakref_type* refs = mPendingWeakDerefs[0];
                mPendingWeakDerefs.removeAt(0);
                refs->decWeak(mProcess.get());
            }
            mPendingWeakDerefs.clear();
        }

        numPending = mPendingStrongDerefs.size();
        if (numPending > 0) {
            for (size_t i = 0; i < numPending; i++) {
                BBinder* obj = mPendingStrongDerefs[i];
            if (mPendingStrongDerefs.size() > 0) {
                // We don't use while() here because we don't want to re-order
                // strong and weak decs at all; if this decStrong() causes both a
                // decWeak() and a decStrong() to be queued, we want to process
                // the decWeak() first.
                BBinder* obj = mPendingStrongDerefs[0];
                mPendingStrongDerefs.removeAt(0);
                obj->decStrong(mProcess.get());
            }
            mPendingStrongDerefs.clear();
        }
    }
}