Skip to content

Commit

Permalink
[Coroutines Interop] Dispose the handle returned by `Job.invokeOnComp…
Browse files Browse the repository at this point in the history
…letion` when Rx subscription is disposed.

The `Completable` `emitter` is captured by the `Job.invokeOnCompletion` closure (`CompletionHandler`), so if we don't dispose the handler when Rx subscription is disposed, we are holding onto a reference to `CompletableEmitter` until the job is completed (and the handler is called and disposed).

Calling the handler after the subscription is disposed is not an issue, because `CompletableEmitter.onError` and `CompletableEmitter.onComplete` checks for disposal before taking any action -- but it stills presents a potential memory leak.
  • Loading branch information
psteiger committed Jul 22, 2023
1 parent 8d6a642 commit b6e372c
Showing 1 changed file with 2 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,13 @@ private fun CoroutineScope.asUndeferredCompletable(): Completable {
val job = coroutineContext[Job] ?: error(
"Scope cannot be created because it does not have a job: ${this@asUndeferredCompletable}"
)
job.invokeOnCompletion {
val handle = job.invokeOnCompletion {
when (it) {
null, is CancellationException -> emitter.onComplete()
else -> emitter.onError(it)
}
}
emitter.setCancellable(handle::dispose)
}
}

Expand Down

0 comments on commit b6e372c

Please sign in to comment.