Provide a runCatching
that does not handle a CancellationException
but re-throws it instead. #1814
Open
Description
Problem Description
The Kotlin StdLib contains a function named runCatching
. It tries the provided lambda and catches any Throwable
that is not caught or thrown by the lambda.
However, using runCatching
in Coroutines can have a somewhat hidden (and unexpected) side-effect of it catching CancellationException
s and not re-throwing them. This could interfere with the Coroutines' Structured Concurrency, with its cancellation handling.
Possible Solution
E.g. create a new function in kotlinx.coroutines that looks something like this
(not sure about the name 😄):
public inline suspend fun <R> runSuspendCatching(block: () -> R): Result<R> {
return try {
Result.success(block())
} catch(c: CancellationException) {
throw c
} catch (e: Throwable) {
Result.failure(e)
}
}
The runSuspendCatching
will catch any exception and wrap it in a Result
, except for CancellationException
s that will be re-thrown instead. This will prevent unwanted interference with the cancellation handling of Coroutines.
Notes
- The
suspend
keyword is added to prevent this new function from being called in regular non-suspending/blocking code. - When code calls the StdLib's
runCatching
in a Coroutine/suspendable-context, a lint warning should warn the developer that handling cancellations may be compromised andrunSuspendCatching
should be used instead.
Metadata
Assignees
Labels
No labels