https://kotlinlang.org logo
#coroutines
Title
# coroutines
e

Erik

05/18/2020, 2:58 PM
I'm confused about the following quote from the
Job
documentation (https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html):
Normal cancellation of a job is distinguished from its failure by the type of its cancellation exception cause. If the cause of cancellation is CancellationException, then the job is considered to be cancelled normally. This usually happens when cancel is invoked without additional parameters. If the cause of cancellation is a different exception, then the job is considered to have failed. This usually happens when the code of the job encounters some problem and throws an exception.
From the first sentence I conclude that a coroutine's
CancellationException
may have a
cause
. From the second sentence I conclude that the
cause
may be yet another
CancellationException
, 😕 am I right? And from the fourth sentence I conclude that, if failed, I will receive a
CancellationException
with a
cause
that is not a
CancellationException
, am I right? So: normally, can a
CancellationException
have another
CancellationException
as its
cause
? If so, can this lead to deep nesting of
CancellationException
instances? And, if so, should traverse this chain of cancellation exceptions in search for a different type of exception to determine if this was a failure or normal cancellation?
z

Zach Klippenstein (he/him) [MOD]

05/18/2020, 3:22 PM
Yes, typically to find the real favor you need to traverse the chain. I use this a lot:
Copy code
generateSequence(e){ it.cause }
  .firstOrNull{ it !is CancellationException }
e

Erik

05/18/2020, 3:37 PM
Do you have an example that would lead to a nested
CancellationException
being caught? I tried creating an example, but I only was able to catch `CancellationException`s without
CancellationException
causes.
z

Zach Klippenstein (he/him) [MOD]

05/18/2020, 3:55 PM
cancel(CancellationException("Oops", cause))
where cause is any other type of exception.
e

Erik

05/18/2020, 3:59 PM
Well, yeah, you can always cancel manually with a
CancellationException
, but that's not what I normally do. Do you have an example where this would normally occur?
It's hard to describe because I can't come up with an example. I can imagine some coroutine structure with many parents and children, where one fails and the rest would be cancelled with the failure as the cause. But I've never seen a failure in a nested
CancellationException
. So does this actually happen if you don't manually nest `CancellationException`s in one another?
f

Fatih

05/18/2020, 6:06 PM
If your question is about work-manager job(I remember you asked earlier), you won't get a reason. Job.cancel() by work-manager will raise a CancellationException without a reason.
e

Erik

05/18/2020, 6:08 PM
Well remembered! However, this is not about that particular use case. I have another case where I check for failure or normal cancellation.
The more I read about the subject, the more I think that `CancellationException`s are normally never nested in a cause chain. (unless you create your own chain of nested cancellation exceptions and cancel a coroutine with it) Furthermore, I log various exceptions caught in coroutines to Crashlytics and I haven't seen a single chain of `CancellationException`: they're all just a single cancellation with an optional cause.
e

elizarov

05/19/2020, 6:58 AM
Yes. The coroutines infrastructure always unwaps CE so that they don’t nest.
👍 2
e

Erik

05/19/2020, 7:01 AM
Well, if 'master coroutine' himself says it, then it must be the truth! 😉 Thank you Roman.
e

elizarov

05/19/2020, 8:03 AM
Here's my attempt to write better docs on that part: https://github.com/Kotlin/kotlinx.coroutines/pull/2035
🎉 1
e

Erik

05/19/2020, 8:37 AM
Wow, thanks! I was about to write something myself or at least create an issue. I'll take a look