Пробрасывается ли ошибка отмены корутины вверх всегда в корутинах

Ответ

Нет, ошибка отмены (CancellationException) не пробрасывается вверх по иерархии корутин. Она обрабатывается внутренне и не вызывает завершение родительской корутины. Это сделано специально, чтобы отмена одной корутины не влияла на другие.

val parentJob = CoroutineScope(Dispatchers.IO).launch {
    val childJob = launch {
        delay(1000)
        throw CancellationException("Child cancelled")
    }
    childJob.join() // Не выбросит исключение в родителя
    println("Parent continues") // Выполнится
}

Однако, если корутина завершается с другой ошибкой (не CancellationException), она может быть проброшена вверх, если не обработана.

Ответ 18+ 🔞

А, ну это классика, ёпта! Сейчас объясню на пальцах, как этот цирк работает.

Представь, что у тебя есть бригада рабочих — это твои корутины. Один из них, Вася, решил, что ему пора на перекур, и просто свалил. Он крикнул: «Я отменён!» — это и есть наш CancellationException. Так вот, бригадир (родительская корутина) на это только плечами пожмёт: «Ну и хуй с ним, пошёл — и ладно». Работа на всей стройке не останавливается, остальные продолжают копать. CancellationException — это вежливая отмазка, внутреннее дело одной корутины, на которое всем да похуй.

Вот смотри, как это в коде выглядит, тут всё честно:

val parentJob = CoroutineScope(Dispatchers.IO).launch {
    val childJob = launch {
        delay(1000)
        throw CancellationException("Child cancelled") // Вася забил на работу
    }
    childJob.join() // Бригадир подождал, пока Вася уйдёт. Исключение НЕ вылетает наружу!
    println("Parent continues") // И спокойно продолжает работать. Эта строчка выполнится.
}

Вот именно так. Родитель спокойно дождётся завершения отменённого ребёнка через join() и пойдёт дальше, без всяких скандалов. Доверия ебать ноль к тому, что ребёнок отработает, но и паники не будет.

А теперь, внимание, хитрая жопа начинается в другом случае. Если Вася-корутина не просто свалил, а, например, уронил на ногу кирпич и заорал от боли — это уже другое исключение, не CancellationException. Вот тут, если эту ошибку не поймать внутри самого ребёнка, она полетит наверх к родителю. И если родитель её тоже не обработает, то может накрыться медным тазом сам и потянуть за собой всех остальных детей в скоупе. Это уже настоящий пиздец, а не культурная отмена.

Короче, запомни: CancellationException — это как сказать «я болен» и уйти домой. Работа других не страдает. Любое другое исключение — это как устроить пожар в офисе. Волнение ебать начинается у всех, и надо быть готовым тушить.