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

Sam

05/11/2019, 9:11 PM
I'm seeing a behavior change between kotlinx-coroutines-core:1.1.0 and kotlinx-coroutines-core:1.2.0 when testing a cancel of launched coroutine within runBlocking (runBlocking is associated with Main dispatcher and launched coroutine with Default dispatcher) 1.1.0 -> runBlocking waits for the CancellationException handling 1.2.0 -> runBlocking finishes before handling of CancellationException Is this on purpose?
Copy code
@RunWith(JUnit4::class)
class CoroutineTest {

    @Test
    fun `test coroutine cancel`() {

        var backgroundWorkCanceled = false

        runBlocking {
            val scope = CoroutineScope( Dispatchers.Default + Job() )
            scope.launch {
                try {
                    backgroundWorkCanceled = false
                    delay(3000)
                } catch( e : CancellationException ) {
                    backgroundWorkCanceled = true
                }
            }
            delay( 2000 )
            scope.cancel()
        }

        assert( backgroundWorkCanceled )
    }
}
It works as expected within a fun main() with both 1.1.0 and 1.2.0. Just that unit test started failing with 1.2.0
l

louiscad

05/11/2019, 9:25 PM
runBlocking doesn't use Dispatchers.Main by default, but creates its own event loop as a dispatcher from the thread it is blocking.
Also, your test breaks structured concurrency as you are creating a custom job instead of just using the job brought by
runBlocking
lambda receiver. Consequently, you face a race condition as `runBlocking returns immediately since your prevent the coroutine you launch from being its child that it would wait for.
You should remove your custom scope and call
launch(Dispatchers.Default)
instead, if you really need to change the dispatcher.
1
s

Sam

05/11/2019, 9:31 PM
Okay, so technically, it should have failed with 1.1.0. So was that just a timing coincidence?
l

louiscad

05/11/2019, 10:05 PM
Or just a race condition that was less likely or impossible to happen in 1.1.0 because of implementation details (that you should not rely on, as you can see).
s

Sam

05/11/2019, 10:05 PM
Okay got it
Thanks
3 Views