question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Stack trace recovery

See original GitHub issue

Look at the example below

fun main(args: Array<String>) = runBlocking {
    xxx()
}


suspend fun xxx() {
    delay(100)
    throw Exception()
}

The execution of the code results to an exception with the incomplete stack trace.

Exception in thread "main" java.lang.Exception
	at TestKt$xxx$1.doResume(Test.kt:20) // throw Exception()
	at kotlin.coroutines.experimental.jvm.internal.CoroutineImpl.resume(CoroutineImpl.kt:54)
        ....
	at TestKt.main(Test.kt:13) //  runBlocking

The stack is starting from the bridge function and completes with the last continuation. All the intermediate calls are missing.

The problem makes it difficult to debug the app because it is not possible to determine the true continuation caller. The stack trace of an exception, thrown from a coroutine, becomes useless.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:15
  • Comments:34 (21 by maintainers)

github_iconTop GitHub Comments

11reactions
matejdrocommented, Jun 21, 2018

How about this one?

fun main(args : Array<String>) {
    runBlocking {
        getData()
    }
}

private suspend fun getData() {
    suspendCoroutine<Unit> { continuation ->
        thread {
            continuation.resumeWithException(Exception("Test Exception"))
        }
    }
}

Running this code will produce this exception:

Exception in thread "main" java.lang.Exception: Test Exception
	at TestKt$getData$2$1.invoke(Test.kt:14)
	at TestKt$getData$2$1.invoke(Test.kt)
	at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)

This exception only works if getData() is called from one place in my application. Otherwise it is very unhelpful, since I have no way of knowing where this method was called.

This is especially frustrating when coroutines is wrapped around 3rd party library such as Google Play services’s Task API. All Google Play code is completely obfuscated, so exceptions will contain only jibberish class names without any hint for where this code is called from.

However, IDEA has “async stracktraces” features where it does capture this kind of information in debug mode.

This is helpful if developer can reproduce the crash in the IDE. But more often than not crashes arrive via crash reporting tools where developer can only see the exception.

7reactions
elizarovcommented, Jul 24, 2017

Here is an update on this issue. Under the most recent version of Kotlin compiler (1.1.4-eap-33) the topic-starter’s example code produces the following stack-trace:

Exception in thread "main" java.lang.Exception
	at TestKt.xxx(Test.kt:10)
	at TestKt$xxx$1.doResume(Test.kt)
...
	at TestKt.main(Test.kt:4)

As you can see, named suspending functions now execute directly in the the correspondingly named functions on JVM, so the top of the exception stack-trace directly refers to the name of the corresponding suspending function that threw exception in the source code.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to get the stacktrace of a panic (and store as a variable)
To make it clear (because this case doesn't explicitly test this): When you're inside recover(), the function debug.Stack() will return the ...
Read more >
Panics, stack traces and how to recover [best practice]
A panic is an exception in Go. Panics are similar to C++ and Java exceptions, but are only intended for run-time errors, such...
Read more >
Using a reverse debugger to recover from stack-corruption
– to rewind one instruction, and the state of the program will move back to the instruction that corrupted the program counter, allowing...
Read more >
Restoring an obfuscated stack trace - IBM
To restore the obfuscated stack trace, you must have a copy of the mapping.txt file that is generated for the release build of...
Read more >
Capturing a stack trace from a recovered panic - Google Groups
I could not find anything for the ?. The system does keep the information as the full stack trace from the recovered panic...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found