Skip to content

Provide a runCatching that does not handle a CancellationException but re-throws it instead. #1814

Open
@Anton-Spaans-Intrepid

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 CancellationExceptions 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 CancellationExceptions 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 and runSuspendCatching should be used instead.

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions