Kotlin Coroutine Context Element Ordering Causing Unexpected Behavior.
I was experimenting with Kotlin coroutine, and noticed some interesting behavior:
Here I am creating a supervisor scope so that the cancellation of the first job should not affect the parent scope and the second job.
The expected behavior is:
- CoroutineExceptionHandler is installed for handling uncaught error
- Scope is created as a SupervisorScope
- With the SupervisorScope, Job 1 and Job 2 are launched
- Job 1 instantly throw error, while Job 2 is waiting for it to join
- Job 1’s cancellation should not cancel Job 2
- Job 1 cancels with exception handled by CorutineExceptionHandler
- Job 2 execute normally, program complete normally
However, upon execute the code output is showing:
Code seems correct, but why the result is not as expected?
Cause of the issue; ordering of adding context elements:
After playing around it a bit with code I noticed that when creating the supervisor scope I was adding coroutine context elements in this order:
val scope = CoroutineScope(ceh + supervisor + coroutineContext)
I added elements in following order:
- custom CoroutineExceptionHandler
- supervisor job
- current coroutineContext from the runBlocking {} scope
And this is causing the unexpected behavior. Turns out the order of which using the + operator to add elements matters!
val scope = CoroutineScope(coroutineContext + ceh + supervisor)