-
Notifications
You must be signed in to change notification settings - Fork 1.9k
[Prototype] exceptions stracktrace recovery #502
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Use Continuation to restore stacktrace First-class support in await() and Channel Prefer constructor with arguments over empty constructor
This would be amazing! I currently do something very similar by injecting the callsite stacktrace as a fake cause of the suspension point exception. |
@@ -144,7 +144,7 @@ public interface DispatchedTask<in T> : Runnable { | |||
else { | |||
val exception = getExceptionalResult(state) | |||
if (exception != null) | |||
continuation.resumeWithException(exception) | |||
continuation.resumeWithException(recoverStackTrace(exception, continuation)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes sense to have cont.resumeWithStackTrace(exception)
extension to simplify boiler-plate in all resumeWithException
invocations.
// TODO multi-release JAR to cache in ClassValueMap | ||
var newException: E? = null | ||
try { | ||
for (constructor in exception.javaClass.constructors.sortedBy { -it.parameterTypes.size }) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sortedByDescending { it.parameterTypes.size }
is longer, but more idiomatic.
@@ -766,7 +766,7 @@ internal open class JobSupport constructor(active: Boolean) : Job, SelectClause0 | |||
val state = this.state | |||
if (state !is Incomplete) { | |||
// already complete -- just return result | |||
if (state is CompletedExceptionally) throw state.cause | |||
if (state is CompletedExceptionally) throw recoverStackTrace(state.cause) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
recoverStackTrace
is missing from JobSupport.awaitSuspend()
. Should find all useages of resumeWithException
and systematically replace them.
return newException | ||
} | ||
|
||
private fun fillInStackTrace(continuation: Continuation<*>): ArrayList<StackTraceElement> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not "fill" anything, so it should be called getStackTrace
.
} | ||
|
||
// TODO basic stub before 1.3 | ||
private fun stackTraceElement(continuation: Continuation<*>): StackTraceElement { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should return a nullable result. An object may not have a stack trace itself, but may be a completion. An good example here is CancellableContinuationImpl
that should be supported.
} | ||
|
||
internal actual fun <E : Throwable> recoverStackTrace(exception: E, continuation: Continuation<*>): E { | ||
if (!DEBUG || exception is CancellationException || continuation !is CoroutineImpl) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
continuation !is CoroutineImpl
is too restrictive for experimental coroutines. CancellableContinuationImpl
shall be supported, too. It is needed for basic example that use Deferred.await()
, for example.
await
and channelThings to do
withContext
supportFixes #493 and (partially) #74