suspend fun test() {
println("test.begin")
delay(5000)
println("test.end")
}
de
lay э
то вызов метода в JVM?
Что произойдёт с тем фреймом, который вызывал delay?
Практика показывает, что если обернуть delay в try-catch, то при cancellation из delay вылетает CancellationException.
Иными словами, «даже после отмены корутины она продолжает выполняться». «какой ужас».
Ещё раз: когда мы (или котлин) делает cancellation, то он «просто» подсылает CancellationException в корутину (грубо говоря resumeWithException(CancellationException()) )
И дальше она сама раскручивается.
Так вот: исходный вызов delay как был обычным jvm вызовом, так и остался. И сам собой со стека он не пропадёт => он пропадёт либо если delay вернёт значение, либо кинет исключение. Так вот: когда delay завершится у нас будет возможность получить нормальный стектрейс.
И тут есть как минимум 2 варианта:
1) На уровне Kotlin компилятора оборачивать все suspended вызовы в try-catch и добавлять к ним «new throwable()» чтобы получать актуальный стек
2) В автомат состояний добавлять доп. информацию. Как-никак, код всё равно «разрезан» по suspended call’ам, значит, мы точно знаем на какой строке кода находились на основе «switch label’а». И мы можем в exception добавить информацию: «кстати, когда пришло cancellation мы находились на такой-то строке кода такого-то метода». Это может быть «дешевле», чем генерировать целиковое исключение