https://kotlinlang.org logo
Title
r

Robert Jaros

11/01/2019, 1:24 PM
Why in this code the exception is printed only once: https://pl.kotl.in/TZrPEdnso If I change
launch
to
GlobalScope.launch
the exception is printed twice: https://pl.kotl.in/13sfoRVtk Shouldn't the unhandled exception cancel the job in both cases?
s

streetsofboston

11/01/2019, 1:39 PM
Your first example causes the outer-most CoroutineScope to be canceled. The second
test.run()
is never called -> One exception printed
Your second example causes the
GlobalScope
to ‘handle’ the exception. It just prints it out and, since it has no
Job
, it never gets canceled, it never finishes. This means that the outer-most CoroutineScope (the one provided by
runBlockingTest
) never gets canceled; the exception didn’t happen in that scope, it happened in the GlobalScope. This means that the code keeps running and
test.run()
is called again
r

Robert Jaros

11/01/2019, 1:48 PM
But in the first example the second
test.run()
IS called. https://pl.kotl.in/CuGYbUKsZ But it never runs its
launch()
block.
I would like to know what really happens after unhandled exception to the CoroutineScope mixed in to my class with
by CoroutineScope(Dispatchers.Default)
. Can it be "fixed" somehow for later use? Or it's just dead? 🙂
Should I just catch all exceptions in the suspending code I launch? Should I use GlobalScope? Are there more ways to get CoroutineScope and launch suspending functions from my class?
s

streetsofboston

11/01/2019, 1:57 PM
Right…. you create a brand new CoroutineScope in which you run the
run
of
Test
Your outer, but separate CoroutineScope (from runBlockingTest) is never canceled and both `test.run()`s are called. However, since the `Test`’s CoroutineScope was canceled by the first call to
test.run()
(exception happened), the 2nd call to
launch
will be canceled immediately
Be careful with creating new CoroutineScopes. Create them for a component's lifecycle. A new CoroutineScopes is a separate new lifecycle. To stay in the same lifecycle along async code calls, stay within the same CoroutineScope. Create a new CoroutineScope when you enter a brand new lifecycle. This should not be the usual case, be careful doing this.
r

Robert Jaros

11/01/2019, 2:13 PM
that's what I'm trying to do. I'm creating CoroutineScope for my component lifecycle. But I wasn't aware the scope gets cancelled after any unhandled exception. For now I'll just catch every exception myself 😉
thx for help
b

bdawg.io

11/01/2019, 7:24 PM
You can use a
SupervisorJob
if you don't want it to cancel
val job = SupervisorJob()
val scope = CoroutineScope(Dispatchers.Main + job)
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-supervisor-job.html
👍 1