From 9f6c80b07df03861af4f5b364c4fb8c7fe942625 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 11 Dec 2024 14:13:26 +0100 Subject: [PATCH] Revisit all @Transient usages in coroutines (#4294) Fixes #4293 --- kotlinx-coroutines-core/jvm/src/Exceptions.kt | 8 +++++++- .../jvm/src/flow/internal/FlowExceptions.kt | 4 ++++ .../jvm/src/internal/CoroutineExceptionHandlerImpl.kt | 6 +++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/kotlinx-coroutines-core/jvm/src/Exceptions.kt b/kotlinx-coroutines-core/jvm/src/Exceptions.kt index a7519862e0..dafaaacbe3 100644 --- a/kotlinx-coroutines-core/jvm/src/Exceptions.kt +++ b/kotlinx-coroutines-core/jvm/src/Exceptions.kt @@ -24,9 +24,15 @@ public actual fun CancellationException(message: String?, cause: Throwable?) : C internal actual class JobCancellationException public actual constructor( message: String, cause: Throwable?, - @JvmField @Transient internal actual val job: Job + job: Job ) : CancellationException(message), CopyableThrowable { + @Transient + private val _job: Job? = job + + // The safest option for transient -- return something that meanigfully reject any attemp to interact with the job + internal actual val job get() = _job ?: NonCancellable + init { if (cause != null) initCause(cause) } diff --git a/kotlinx-coroutines-core/jvm/src/flow/internal/FlowExceptions.kt b/kotlinx-coroutines-core/jvm/src/flow/internal/FlowExceptions.kt index d8c46d2a76..02817396e8 100644 --- a/kotlinx-coroutines-core/jvm/src/flow/internal/FlowExceptions.kt +++ b/kotlinx-coroutines-core/jvm/src/flow/internal/FlowExceptions.kt @@ -2,6 +2,10 @@ package kotlinx.coroutines.flow.internal import kotlinx.coroutines.* +/** + * Implementation note: `owner` is an internal marked that is used ONLY for identity checks by coroutines machinery, + * and it's never exposed, thus it's safe to have it both `@Transient` and non-nullable. + */ internal actual class AbortFlowException actual constructor( @JvmField @Transient actual val owner: Any ) : CancellationException("Flow was aborted, no more elements needed") { diff --git a/kotlinx-coroutines-core/jvm/src/internal/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/jvm/src/internal/CoroutineExceptionHandlerImpl.kt index 0014e1742f..2d048ac71a 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/CoroutineExceptionHandlerImpl.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/CoroutineExceptionHandlerImpl.kt @@ -32,7 +32,11 @@ internal actual fun propagateExceptionFinalResort(exception: Throwable) { } // This implementation doesn't store a stacktrace, which is good because a stacktrace doesn't make sense for this. -internal actual class DiagnosticCoroutineContextException actual constructor(@Transient private val context: CoroutineContext) : RuntimeException() { +internal actual class DiagnosticCoroutineContextException actual constructor(context: CoroutineContext) : RuntimeException() { + + @Transient + private val context: CoroutineContext? = context + override fun getLocalizedMessage(): String { return context.toString() }