aboutsummaryrefslogtreecommitdiffstats
path: root/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt
diff options
context:
space:
mode:
Diffstat (limited to 'kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt')
-rw-r--r--kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt14
1 files changed, 10 insertions, 4 deletions
diff --git a/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt b/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt
index 48e8790c..174c57b7 100644
--- a/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt
+++ b/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt
@@ -29,7 +29,7 @@ private val stackTraceRecoveryClassName = runCatching {
internal actual fun <E : Throwable> recoverStackTrace(exception: E): E {
if (!RECOVER_STACK_TRACES) return exception
// No unwrapping on continuation-less path: exception is not reported multiple times via slow paths
- val copy = tryCopyException(exception) ?: return exception
+ val copy = tryCopyAndVerify(exception) ?: return exception
return copy.sanitizeStackTrace()
}
@@ -66,9 +66,7 @@ private fun <E : Throwable> recoverFromStackFrame(exception: E, continuation: Co
val (cause, recoveredStacktrace) = exception.causeAndStacktrace()
// Try to create an exception of the same type and get stacktrace from continuation
- val newException = tryCopyException(cause) ?: return exception
- // Verify that the new exception has the same message as the original one (bail out if not, see #1631)
- if (newException.message != cause.message) return exception
+ val newException = tryCopyAndVerify(cause) ?: return exception
// Update stacktrace
val stacktrace = createStackTrace(continuation)
if (stacktrace.isEmpty()) return exception
@@ -80,6 +78,14 @@ private fun <E : Throwable> recoverFromStackFrame(exception: E, continuation: Co
return createFinalException(cause, newException, stacktrace)
}
+private fun <E : Throwable> tryCopyAndVerify(exception: E): E? {
+ val newException = tryCopyException(exception) ?: return null
+ // Verify that the new exception has the same message as the original one (bail out if not, see #1631)
+ // CopyableThrowable has control over its message and thus can modify it the way it wants
+ if (exception !is CopyableThrowable<*> && newException.message != exception.message) return null
+ return newException
+}
+
/*
* Here we partially copy original exception stackTrace to make current one much prettier.
* E.g. for