Skip to content

Instantly share code, notes, and snippets.

@romansl
Created February 5, 2018 14:17
Show Gist options
  • Save romansl/f6c6faa9ab08a22cf035b10f907993b6 to your computer and use it in GitHub Desktop.
Save romansl/f6c6faa9ab08a22cf035b10f907993b6 to your computer and use it in GitHub Desktop.
class CoroutineException(message: String) : RuntimeException(message)
class MyExceptionHandler(private val delegate: CoroutineExceptionHandler) :
AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler
{
override fun handleException(context: CoroutineContext, exception: Throwable) {
val ci = context[ContinuationInterceptor] as? DebugInterceptor
val ce = ci?.ce
val e = if (ce == null) {
exception
} else {
ce.initCause(exception)
}
e.printStackTrace()
// FIXME: Вызов этой строчки не крашит приложение. Не знаю почему.
delegate.handleException(context, e)
}
}
class DebugInterceptor(private val wrapped: CoroutineDispatcher) : CoroutineDispatcher() {
@Volatile
var ce: CoroutineException? = null
override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> {
// Создаем, но не бросаем исключение.
// Так как исключение сохраняется раньше, чем будет вызван следующий шаг стейт машины,
// то строчка в стектрейсе будет отличаться на одну выше реального места возникновения,
// а то и вовсе будет указывать куда попало. Возможно нужно выбрать какое-то другое место.
ce = CoroutineException("")
return super.interceptContinuation(continuation)
}
override fun dispatch(context: CoroutineContext, block: Runnable) {
wrapped.dispatch(context, block)
}
override fun toString(): String = "DebugInterceptor"
}
fun foo() {
launch(DebugInterceptor(UI) + MyExceptionHandler(AndroidExceptionPreHandler())) {
delay(100)
bar()
}
}
suspend fun bar() {
delay(100)
throw RuntimeException("Hello")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment