Kotlin:在协程中展开 CancellationException

Kotlin: CancellationException unwrapping in coroutines

我在文档中找到了下一条语句:

Cancellation exceptions are transparent and are unwrapped by default:

val handler = CoroutineExceptionHandler { _, exception -> println("CoroutineExceptionHandler got $exception")
}
val job = GlobalScope.launch(handler) {
    val inner = launch { // all this stack of coroutines will get cancelled 
        launch {
            launch {
                throw IOException() // the original exception
            } 
        }
    }
    try {
        inner.join()
    } catch (e: CancellationException) {
        println("Rethrowing CancellationException with original cause")
        throw e // cancellation exception is rethrown, yet the original IOException gets to the handler
    } 
}
job.join()

此文档对这段代码意味着什么?

更新 27-03-2021

import kotlinx.coroutines.*
import java.io.*

fun main() = runBlocking {
    val handler = CoroutineExceptionHandler { _, exception ->
        println("CoroutineExceptionHandler got $exception")
    }
    val job = GlobalScope.launch(handler) {
        launch {
            throw IOException() // the original exception
        }
        launch {
            throw CancellationException("Test", ArithmeticException("Arithmetic"))
        }
    }
    job.join()
}

为什么在这种情况下结果是:

CoroutineExceptionHandler got java.io.IOException

没有算术异常?

inner.join() 抛出一个 CancellationException,原因设置为在作业中抛出的异常。但是当 CancellationException 在顶层出现时,CoroutineExceptionHandler 只会看到 IOExceptionCancellationException 的原因)。