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

Commit 074b8b7c authored by Jeff Brown's avatar Jeff Brown
Browse files

Eliminate potential reentrance from unregisterInputChannel.

Ensure that all callbacks into the window manager policy occur
on the input dispatcher thread in the right place.  This fixes
a potential deadlock that may occur if the window manager
unregisters an input channel while holding its own lock.

The change is simply to defer running asynchronous commands
(usually callbacks into the policy) until the next iteration
of the dispatch looper thread.

Bug: 7382388
Change-Id: I90095580d717fcddb2209ef332df56400f837a34
parent c8dc8eb3
Loading
Loading
Loading
Loading
+15 −6
Original line number Diff line number Diff line
@@ -224,10 +224,16 @@ void InputDispatcher::dispatchOnce() {
        AutoMutex _l(mLock);
        mDispatcherIsAliveCondition.broadcast();

        // Run a dispatch loop if there are no pending commands.
        // The dispatch loop might enqueue commands to run afterwards.
        if (!haveCommandsLocked()) {
            dispatchOnceInnerLocked(&nextWakeupTime);
        }

        // Run all pending commands if there are any.
        // If any commands were run then force the next poll to wake up immediately.
        if (runCommandsLockedInterruptible()) {
            nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
            nextWakeupTime = LONG_LONG_MIN;
        }
    } // release lock

@@ -562,6 +568,10 @@ bool InputDispatcher::isStaleEventLocked(nsecs_t currentTime, EventEntry* entry)
    return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT;
}

bool InputDispatcher::haveCommandsLocked() const {
    return !mCommandQueue.isEmpty();
}

bool InputDispatcher::runCommandsLockedInterruptible() {
    if (mCommandQueue.isEmpty()) {
        return false;
@@ -3247,9 +3257,10 @@ status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChan
        }

        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);

        runCommandsLockedInterruptible();
    } // release lock

    // Wake the looper because some connections have changed.
    mLooper->wake();
    return OK;
}

@@ -3294,8 +3305,6 @@ status_t InputDispatcher::unregisterInputChannelLocked(const sp<InputChannel>& i
    nsecs_t currentTime = now();
    abortBrokenDispatchCycleLocked(currentTime, connection, notify);

    runCommandsLockedInterruptible();

    connection->status = Connection::STATUS_ZOMBIE;
    return OK;
}
+1 −0
Original line number Diff line number Diff line
@@ -899,6 +899,7 @@ private:
    KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime);

    // Deferred command processing.
    bool haveCommandsLocked() const;
    bool runCommandsLockedInterruptible();
    CommandEntry* postCommandLocked(Command command);