Skip to content

Usually, await throws a wrong exception for representing a failure of a Deferred (e.g., of an async coroutine) #2086

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
taras-i-fedyk opened this issue Jun 11, 2020 · 2 comments

Comments

@taras-i-fedyk
Copy link

taras-i-fedyk commented Jun 11, 2020

The current behavior: awaiting the result of a Deferred (e.g., of an async coroutine) throws the original exception in the current coroutine when the current coroutine is failing or is being cancelled as a result of the Deferred’s failure (e.g., of the async coroutine's failure).

The proposed behavior: await throws a CancellationException in such cases instead.

Here are the reasons why the proposed behavior would be much more appropriate:

  • the proposed behavior would conform to the paradigm in accordance with which a suspending function throws a CancellationException when the current coroutine is failing or is being cancelled.

  • the proposed behavior would be consistent with how Job.join and ReceiveChannel.receive work.

  • the proposed behavior would not create the illusion that you can catch the exception generated by a failed Deferred (e.g., by a failed async coroutine) for the sake of preventing its parent coroutine from failing automatically.

    Because if you're told that await can throw only a CancellationException under the given circumstances, you understand that once some exception has been thrown, Structured Concurrency has been already applied and you can’t undo it. Thus you know beforehand that the effect of catching an exception is limited, and such a limited effect doesn't contradict common sense.

@taras-i-fedyk taras-i-fedyk changed the title Await throws a wrong exception for representing a failure inside Async Await throws a wrong exception for representing a failure inside a Deferred (e.g., inside an Async coroutine) Jun 11, 2020
@taras-i-fedyk taras-i-fedyk changed the title Await throws a wrong exception for representing a failure inside a Deferred (e.g., inside an Async coroutine) Await throws a wrong exception for representing a failure of a Deferred (e.g., of an Async coroutine) Jun 12, 2020
@taras-i-fedyk taras-i-fedyk changed the title Await throws a wrong exception for representing a failure of a Deferred (e.g., of an Async coroutine) Usually, await throws a wrong exception for representing a failure of a Deferred (e.g., of an async coroutine) Jun 12, 2020
@elizarov
Copy link
Contributor

The ship has sailed with respect to how .await() works and it works this way by design, to ensure that computation can be transparently moved to another coroutine while perfectly preserving its resulting value and resulting exceptions, e.g.

val d = scope.async { doSomething() }
d.await()

Should behave identically to:

doSomething()

@taras-i-fedyk
Copy link
Author

taras-i-fedyk commented Jun 17, 2020

@elizarov

When the parent scope is such that it automatically fails after a child scope has failed: the two pieces of code you gave as an example cannot have the "same" semantics in principle. Consequently, those pieces of code don't have the "same" semantics at present, despite the fact that the current behavior of await was designed specifically for ensuring the "sameness" in question. If so, the current behavior of await doesn't make much sense. And taking into account the fact that it also leads to the significant drawbacks pointed out in my initial post, the current behavior is indeed much less appropriate than the proposed one described in that post.

When the parent scope is NOT such that it automatically fails after a child scope has failed: the two pieces of code you gave as an example do have the "same" semantics. However, my complaints regarding the current behavior of await are in no way related to such cases, as mentioned in my initial post.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants