From 14fa5a7e4f4ac26bd4eaabfed446ffddbe99d6c3 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 23 Jul 2019 15:40:27 +0300 Subject: [PATCH 1/3] Fully copy CoroutineInfo for DebugProbes.dumpCoroutinesInfo, it is required for IDEA integration (field is left as internal deliberately) --- .../kotlinx-coroutines-debug.txt | 1 + kotlinx-coroutines-debug/src/CoroutineInfo.kt | 12 ++++-------- .../src/internal/DebugProbesImpl.kt | 6 +++--- .../test/RunningThreadStackMergeTest.kt | 11 +++++++++++ 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt index 604e6cd253..924af9244e 100644 --- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt +++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt @@ -1,5 +1,6 @@ public final class kotlinx/coroutines/debug/CoroutineInfo { public final fun component1 ()Lkotlin/coroutines/CoroutineContext; + public final fun copy ()Lkotlinx/coroutines/debug/CoroutineInfo; public final fun copy (Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/jvm/internal/CoroutineStackFrame;J)Lkotlinx/coroutines/debug/CoroutineInfo; public static synthetic fun copy$default (Lkotlinx/coroutines/debug/CoroutineInfo;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/jvm/internal/CoroutineStackFrame;JILjava/lang/Object;)Lkotlinx/coroutines/debug/CoroutineInfo; public fun equals (Ljava/lang/Object;)Z diff --git a/kotlinx-coroutines-debug/src/CoroutineInfo.kt b/kotlinx-coroutines-debug/src/CoroutineInfo.kt index 56f391a203..34e270396e 100644 --- a/kotlinx-coroutines-debug/src/CoroutineInfo.kt +++ b/kotlinx-coroutines-debug/src/CoroutineInfo.kt @@ -44,14 +44,10 @@ public data class CoroutineInfo internal constructor( @JvmField internal var lastObservedFrame: CoroutineStackFrame? = null - // Copy constructor - internal constructor(coroutine: Continuation<*>, state: CoroutineInfo) : this( - coroutine.context, - state.creationStackBottom, - state.sequenceNumber - ) { - _state = state.state - this.lastObservedFrame = state.lastObservedFrame + public fun copy(): CoroutineInfo = CoroutineInfo(context, creationStackBottom, sequenceNumber).also { + it._state = _state + it.lastObservedFrame = lastObservedFrame + it.lastObservedThread = lastObservedThread } /** diff --git a/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt b/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt index 29b1e36e09..b8b01c3587 100644 --- a/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt +++ b/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt @@ -80,7 +80,7 @@ internal object DebugProbesImpl { check(isInstalled) { "Debug probes are not installed" } val jobToStack = capturedCoroutines .filter { it.delegate.context[Job] != null } - .associateBy({ it.delegate.context[Job]!! }, {it.info}) + .associateBy({ it.delegate.context[Job]!! }, { it.info }) return buildString { job.build(jobToStack, this, "") } @@ -118,7 +118,7 @@ internal object DebugProbesImpl { public fun dumpCoroutinesInfo(): List { check(isInstalled) { "Debug probes are not installed" } return capturedCoroutines.asSequence() - .map { CoroutineInfo(it.delegate, it.info) } + .map { it.info.copy() } // Copy as CoroutineInfo can be mutated concurrently by DebugProbes .sortedBy { it.sequenceNumber } .toList() } @@ -373,7 +373,7 @@ internal object DebugProbesImpl { private fun sanitizeStackTrace(throwable: T): List { val stackTrace = throwable.stackTrace val size = stackTrace.size - val probeIndex = stackTrace.indexOfLast { it.className == "kotlin.coroutines.jvm.internal.DebugProbesKt" } + val probeIndex = stackTrace.indexOfLast { it.className == "kotlin.coroutines.jvm.internal.DebugProbesKt" } if (!DebugProbes.sanitizeStackTraces) { return List(size - probeIndex) { diff --git a/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt b/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt index 3ccbe0ae00..c15fe89487 100644 --- a/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt +++ b/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt @@ -167,4 +167,15 @@ class RunningThreadStackMergeTest : DebugTestBase() { yield() assertTrue(true) } + + @Test + fun testActiveThread() = runBlocking { + launchCoroutine() + awaitCoroutineStarted() + val info = DebugProbes.dumpCoroutinesInfo().find { it.state == State.RUNNING } + assertNotNull(info) + @Suppress("INVISIBLE_MEMBER") // IDEA bug + assertNotNull(info.lastObservedThread) + coroutineBlocker.await() + } } From 80c80549fdbd4e39485fb02a615d7e96b5567dfb Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Mon, 5 Aug 2019 19:04:48 +0300 Subject: [PATCH 2/3] Make CoroutineInfo non-data class --- .../reference-public-api/kotlinx-coroutines-debug.txt | 5 ----- kotlinx-coroutines-debug/src/CoroutineInfo.kt | 6 +++++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt index 924af9244e..79f5b75d15 100644 --- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt +++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt @@ -1,14 +1,9 @@ public final class kotlinx/coroutines/debug/CoroutineInfo { - public final fun component1 ()Lkotlin/coroutines/CoroutineContext; public final fun copy ()Lkotlinx/coroutines/debug/CoroutineInfo; - public final fun copy (Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/jvm/internal/CoroutineStackFrame;J)Lkotlinx/coroutines/debug/CoroutineInfo; - public static synthetic fun copy$default (Lkotlinx/coroutines/debug/CoroutineInfo;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/jvm/internal/CoroutineStackFrame;JILjava/lang/Object;)Lkotlinx/coroutines/debug/CoroutineInfo; - public fun equals (Ljava/lang/Object;)Z public final fun getContext ()Lkotlin/coroutines/CoroutineContext; public final fun getCreationStackTrace ()Ljava/util/List; public final fun getJob ()Lkotlinx/coroutines/Job; public final fun getState ()Lkotlinx/coroutines/debug/State; - public fun hashCode ()I public final fun lastObservedStackTrace ()Ljava/util/List; public fun toString ()Ljava/lang/String; } diff --git a/kotlinx-coroutines-debug/src/CoroutineInfo.kt b/kotlinx-coroutines-debug/src/CoroutineInfo.kt index 34e270396e..9d2fc99120 100644 --- a/kotlinx-coroutines-debug/src/CoroutineInfo.kt +++ b/kotlinx-coroutines-debug/src/CoroutineInfo.kt @@ -14,7 +14,7 @@ import kotlin.coroutines.jvm.internal.* * Class describing coroutine info such as its context, state and stacktrace. */ @ExperimentalCoroutinesApi -public data class CoroutineInfo internal constructor( +public class CoroutineInfo internal constructor( val context: CoroutineContext, private val creationStackBottom: CoroutineStackFrame, @JvmField internal val sequenceNumber: Long @@ -90,6 +90,10 @@ public data class CoroutineInfo internal constructor( lastObservedThread = null } } + + override fun toString(): String { + return "CoroutineInfo(state=$state,context=$context)" + } } /** From ae034ae7e935a91da5a2c54c814a363a0f690e6b Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 9 Aug 2019 17:35:38 +0300 Subject: [PATCH 3/3] ~ --- kotlinx-coroutines-debug/src/CoroutineInfo.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kotlinx-coroutines-debug/src/CoroutineInfo.kt b/kotlinx-coroutines-debug/src/CoroutineInfo.kt index 9d2fc99120..84cd9f370e 100644 --- a/kotlinx-coroutines-debug/src/CoroutineInfo.kt +++ b/kotlinx-coroutines-debug/src/CoroutineInfo.kt @@ -91,9 +91,7 @@ public class CoroutineInfo internal constructor( } } - override fun toString(): String { - return "CoroutineInfo(state=$state,context=$context)" - } + override fun toString(): String = "CoroutineInfo(state=$state,context=$context)" } /**