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

Commit 3b1ef1e9 authored by Steve Elliott's avatar Steve Elliott
Browse files

[kairos] guard against coroutine cancelation race

A rare edge case can occur where an observer is added to a BuildScope
that is mid-cancelation, something which is completely valid.

The bug: when adding a completion handler to the build scope's internal
coroutine scope, if this scope is mid-cancellation, then the completion
handler is invoked immediately. This caused an uninitialized variable
`cancelHandle` to be accessed, resulting in a crash.

The solution: remove `lateinit`, make `cancelHandle` nullable, perform
explicit null checking.

Flag: com.android.systemui.status_bar_mobile_icon_kairos
Bug: 383172066
Change-Id: Ie6bb938bef13bb7685b50a19241136bcc575512d
parent f644021a
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -113,11 +113,11 @@ internal class BuildScopeImpl(val stateScope: StateScopeImpl, val coroutineScope
        coroutineContext: CoroutineContext,
        block: EffectScope.(A) -> Unit,
    ): DisposableHandle {
        val subRef = AtomicReference<Maybe<Output<A>>>(null)
        val subRef = AtomicReference<Maybe<Output<A>>?>(null)
        val childScope = coroutineScope.childScope()
        lateinit var cancelHandle: DisposableHandle
        var cancelHandle: DisposableHandle? = null
        val handle = DisposableHandle {
            cancelHandle.dispose()
            cancelHandle?.dispose()
            subRef.getAndSet(Absent)?.let { output ->
                if (output is Present) {
                    @Suppress("DeferredResultUnused")