Elye
Elye

Reputation: 60141

Why CoroutineExceptionHandler can only perform launch when the coroutineContext is MainScope()?

I have the below code and purposely trigger an exception to be caught by errorHandler

    private var coroutineScope: CoroutineScope? = null
    private val mainThreadSurrogate = newSingleThreadContext("Test Main")

    @Before
    fun setUp() {
        Dispatchers.setMain(mainThreadSurrogate)
    }

    @After
    fun tearDown() {
        // reset main dispatcher to the original Main dispatcher       
        Dispatchers.resetMain()
        mainThreadSurrogate.close()
    }

    private val errorHandler = CoroutineExceptionHandler { context, error ->
        println("Launch Exception ${Thread.currentThread()}")
        coroutineScope?.launch(Dispatchers.Main) {
            println("Launch Exception Result ${Thread.currentThread()}")
        }
    }

    @Test
    fun testData() {
        runBlocking {
            coroutineScope = MainScope()
            coroutineScope?.launch(errorHandler) {
                println("Launch Fetch Started ${Thread.currentThread()}")
                throw IllegalStateException("error")
            }?.join()
        }
    }

This will result in

Launch Fetch Started Thread[Test Main @coroutine#2,5,main]
Launch Exception Thread[Test Main @coroutine#2,5,main]
Launch Exception Result Thread[Test Main @coroutine#3,5,main]

If I change coroutineScope = MainScope() to either

The coroutineScope?.launch(Dispatchers.Main) {...} will not run i.e. the Launch Exception Result ... will not get printed.

Why is it so?

Upvotes: 0

Views: 829

Answers (1)

Elye
Elye

Reputation: 60141

Apparently, we need to create a Scope using SupervisorJob(), so that the parent job is not affected by the child job crash.

coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)

Note the MainScope() is CoroutineScope(SupervisorJob() + Dispatchers.Main).

As mentioned in SupervisorJob

A failure or cancellation of a child does not cause the supervisor job to fail and does not affect its other children, so a supervisor can implement a custom policy for handling failures of its children

Upvotes: 1

Related Questions