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

Commit 36a9ecd9 authored by Phil Burk's avatar Phil Burk Committed by Anis Assi
Browse files

aaudio: fix race when disconnecting

When disconnecting more than one stream,
and the apps reopen the streams,
there was a race condition that resulted
in the first app getting a Legacy stream instead of an
MMAP stream. That is because it was disconnected before the
other streams had stopped.

Now we run the stop loop before the disconnect loop
to prevent the race.

Bug: 153358911
Bug: 158316262
Test: test_steal_exclusive -r0 -d0 -s
Change-Id: Ib8efde9c2f94f6ab1ba3475d88b45d373cc8d3bb
Merged-In: Ib8efde9c2f94f6ab1ba3475d88b45d373cc8d3bb
(cherry picked from commit 8e2255ad)
(cherry picked from commit 50fd22f3)
parent a6a3ff71
Loading
Loading
Loading
Loading
+9 −3
Original line number Original line Diff line number Diff line
@@ -95,10 +95,16 @@ void AAudioServiceEndpoint::disconnectRegisteredStreams() {
    // Stop and disconnect outside mLockStreams to avoid reverse
    // Stop and disconnect outside mLockStreams to avoid reverse
    // ordering of AAudioServiceStreamBase::mLock and mLockStreams
    // ordering of AAudioServiceStreamBase::mLock and mLockStreams
    mConnected.store(false);
    mConnected.store(false);
    // We need to stop all the streams before we disconnect them.
    // Otherwise there is a race condition where the first disconnected app
    // tries to reopen a stream as MMAP but is blocked by the second stream,
    // which hasn't stopped yet. Then the first app ends up with a Legacy stream.
    for (const auto &stream : streamsToDisconnect) {
    for (const auto &stream : streamsToDisconnect) {
        ALOGD("disconnectRegisteredStreams() stop and disconnect port %d",
        ALOGD("%s() - stop(), port = %d", __func__, stream->getPortHandle());
              stream->getPortHandle());
        stream->stop();
        stream->stop();
    }
    for (const auto &stream : streamsToDisconnect) {
        ALOGD("%s() - disconnect(), port = %d", __func__, stream->getPortHandle());
        stream->disconnect();
        stream->disconnect();
    }
    }
}
}