diff options
Diffstat (limited to 'kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt')
-rw-r--r-- | kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt | 14 |
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 |