question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Newly created Jobs considered as cancelled after only 1 occurence of an exception

See original GitHub issue

Hello,

I am trying to build an async flow whose role is to merge identical calls into one (but that is not really related to this bug) https://github.com/libetl/coroutines-pooling-client

I am using an CoroutineScope.async operation where I happen to throw an exception in case of an error received from the user implementation. https://github.com/libetl/coroutines-pooling-client/blob/master/src/main/kotlin/org/toilelibre/libe/poolingclient/PoolingClientStrategy.kt#L153

The flow starts failing systematically once the first exception bubbled up, making all the coroutine executor threads to vanish.

Once the first ResultFailure is read, the statement https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/common/src/CompletedExceptionally.kt#L12 always decides to use CompletedExceptionally class while I am expecting to have a call to throwOnFailure().

As a result, every subsequent call to the same async operation will call recoverAndThrow https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt#L150 and will keep on returning the previously bubbled up exception instead of re-executing the user implementation.

  1. Did I make myself clear enough in the above description ?
  2. Is it an expected behaviour ?
  3. What could have gone wrong ?
  4. Thank you for your help

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
libetlcommented, Aug 15, 2019

Thanks, that was exactly the piece of advice I needed. I changed the context to be SupervisorJob and the new jobs remain healthy even after a failure.

0reactions
zach-klippensteincommented, Aug 15, 2019

All your async jobs share a common parent job, which lives in coroutineScope. The first time any of those jobs fail (you throw an UOE), that exception gets stored in the Deferred, but it also gets reported to the parent job, in coroutineScope, which cancels that job and stores the failure there as well. This happens The first time toRun[0] calls await(). The next time you try using that job to launch a new coroutine (i.e. when toRun[1] calls await), it won’t even get started because the parent job is already cancelled, and the resulting Deferred will just immediately report the same error.

async is weird like that, it reports exceptions both up (to its parent) and down (to the Deferred).

In your test, you can fix this by making the parent job a SupervisorJob:

val coroutineScope = CoroutineScope(SupervisorJob())

SupervisorJob “is similar to a regular Job with the only exception that cancellation is propagated only downwards.”

Read more comments on GitHub >

github_iconTop Results From Across the Web

Java Exceptions And Exception Handling With Examples
When an exception occurs in the program, the program execution is terminated. As this is an abrupt termination, the system generates a message ......
Read more >
The employment-at-will doctrine: three major exceptions
Another widely recognized exception prohibits termi- nations after an implied contract for employment has been established; such a contract can be created ......
Read more >
Recommended patterns for CancellationToken
Don't throw OperationCanceledException after you've completed the work, just because the token was signaled. Return a successful result and ...
Read more >
The Federal Work-Study Program - FSA Partner Connect
Working During Scheduled Class Time Prohibited​​ Any such exemptions must be documented.
Read more >
Exception handling - Wikipedia
In computing and computer programming, exception handling is the process of responding to the occurrence of exceptions – anomalous or exceptional conditions ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found