Skip to content

Commit fe1763c

Browse files
dkhalanskyjbpablobaxter
authored andcommitted
Revert displaying fake stack frames as method calls (Kotlin#2695)
Reverts commit Kotlin@b61a66c
1 parent 01027c2 commit fe1763c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+143
-177
lines changed

docs/images/after.png

134 KB
Loading

docs/images/before.png

61.8 KB
Loading

kotlinx-coroutines-core/jvm/src/debug/CoroutineDebugging.kt

-65
This file was deleted.

kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt

+18-16
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package kotlinx.coroutines.debug.internal
77
import kotlinx.atomicfu.*
88
import kotlinx.coroutines.*
99
import kotlinx.coroutines.debug.*
10+
import kotlinx.coroutines.internal.*
1011
import kotlinx.coroutines.internal.ScopeCoroutine
1112
import java.io.*
1213
import java.lang.StackTraceElement
@@ -17,10 +18,10 @@ import kotlin.concurrent.*
1718
import kotlin.coroutines.*
1819
import kotlin.coroutines.jvm.internal.CoroutineStackFrame
1920
import kotlin.synchronized
20-
import _COROUTINE.ArtificialStackFrames
21+
import kotlinx.coroutines.internal.artificialFrame as createArtificialFrame // IDEA bug workaround
2122

2223
internal object DebugProbesImpl {
23-
private val ARTIFICIAL_FRAME = ArtificialStackFrames().coroutineCreation()
24+
private const val ARTIFICIAL_FRAME_MESSAGE = "Coroutine creation stacktrace"
2425
private val dateFormat = SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
2526

2627
private var weakRefCleanerThread: Thread? = null
@@ -218,7 +219,7 @@ internal object DebugProbesImpl {
218219
info.state
219220
out.print("\n\nCoroutine ${owner.delegate}, state: $state")
220221
if (observedStackTrace.isEmpty()) {
221-
out.print("\n\tat $ARTIFICIAL_FRAME")
222+
out.print("\n\tat ${createArtificialFrame(ARTIFICIAL_FRAME_MESSAGE)}")
222223
printStackTrace(out, info.creationStackTrace)
223224
} else {
224225
printStackTrace(out, enhancedStackTrace)
@@ -420,17 +421,15 @@ internal object DebugProbesImpl {
420421
return createOwner(completion, frame)
421422
}
422423

423-
private fun List<StackTraceElement>.toStackTraceFrame(): StackTraceFrame =
424-
StackTraceFrame(
425-
foldRight<StackTraceElement, StackTraceFrame?>(null) { frame, acc ->
426-
StackTraceFrame(acc, frame)
427-
}, ARTIFICIAL_FRAME
428-
)
424+
private fun List<StackTraceElement>.toStackTraceFrame(): StackTraceFrame? =
425+
foldRight<StackTraceElement, StackTraceFrame?>(null) { frame, acc ->
426+
StackTraceFrame(acc, frame)
427+
}
429428

430429
private fun <T> createOwner(completion: Continuation<T>, frame: StackTraceFrame?): Continuation<T> {
431430
if (!isInstalled) return completion
432431
val info = DebugCoroutineInfoImpl(completion.context, frame, sequenceNumber.incrementAndGet())
433-
val owner = CoroutineOwner(completion, info)
432+
val owner = CoroutineOwner(completion, info, frame)
434433
capturedCoroutinesMap[owner] = true
435434
if (!isInstalled) capturedCoroutinesMap.clear()
436435
return owner
@@ -453,9 +452,9 @@ internal object DebugProbesImpl {
453452
*/
454453
private class CoroutineOwner<T>(
455454
@JvmField val delegate: Continuation<T>,
456-
@JvmField val info: DebugCoroutineInfoImpl
455+
@JvmField val info: DebugCoroutineInfoImpl,
456+
private val frame: CoroutineStackFrame?
457457
) : Continuation<T> by delegate, CoroutineStackFrame {
458-
private val frame get() = info.creationStackBottom
459458

460459
override val callerFrame: CoroutineStackFrame?
461460
get() = frame?.callerFrame
@@ -473,10 +472,12 @@ internal object DebugProbesImpl {
473472
private fun <T : Throwable> sanitizeStackTrace(throwable: T): List<StackTraceElement> {
474473
val stackTrace = throwable.stackTrace
475474
val size = stackTrace.size
476-
val traceStart = 1 + stackTrace.indexOfLast { it.className == "kotlin.coroutines.jvm.internal.DebugProbesKt" }
475+
val probeIndex = stackTrace.indexOfLast { it.className == "kotlin.coroutines.jvm.internal.DebugProbesKt" }
477476

478477
if (!sanitizeStackTraces) {
479-
return List(size - traceStart) { stackTrace[it + traceStart] }
478+
return List(size - probeIndex) {
479+
if (it == 0) createArtificialFrame(ARTIFICIAL_FRAME_MESSAGE) else stackTrace[it + probeIndex]
480+
}
480481
}
481482

482483
/*
@@ -487,8 +488,9 @@ internal object DebugProbesImpl {
487488
* If an interval of internal methods ends in a synthetic method, the outermost non-synthetic method in that
488489
* interval will also be included.
489490
*/
490-
val result = ArrayList<StackTraceElement>(size - traceStart + 1)
491-
var i = traceStart
491+
val result = ArrayList<StackTraceElement>(size - probeIndex + 1)
492+
result += createArtificialFrame(ARTIFICIAL_FRAME_MESSAGE)
493+
var i = probeIndex + 1
492494
while (i < size) {
493495
if (stackTrace[i].isInternalMethod) {
494496
result += stackTrace[i] // we include the boundary of the span in any case

kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt

+9-8
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
package kotlinx.coroutines.internal
88

99
import kotlinx.coroutines.*
10-
import _COROUTINE.ARTIFICIAL_FRAME_PACKAGE_NAME
11-
import _COROUTINE.ArtificialStackFrames
1210
import java.util.*
1311
import kotlin.coroutines.*
1412
import kotlin.coroutines.intrinsics.*
@@ -20,8 +18,6 @@ import kotlin.coroutines.intrinsics.*
2018
private const val baseContinuationImplClass = "kotlin.coroutines.jvm.internal.BaseContinuationImpl"
2119
private const val stackTraceRecoveryClass = "kotlinx.coroutines.internal.StackTraceRecoveryKt"
2220

23-
private val ARTIFICIAL_FRAME = ArtificialStackFrames().coroutineBoundary()
24-
2521
private val baseContinuationImplClassName = runCatching {
2622
Class.forName(baseContinuationImplClass).canonicalName
2723
}.getOrElse { baseContinuationImplClass }
@@ -46,7 +42,7 @@ private fun <E : Throwable> E.sanitizeStackTrace(): E {
4642
val adjustment = if (endIndex == -1) 0 else size - endIndex
4743
val trace = Array(size - lastIntrinsic - adjustment) {
4844
if (it == 0) {
49-
ARTIFICIAL_FRAME
45+
artificialFrame("Coroutine boundary")
5046
} else {
5147
stackTrace[startIndex + it - 1]
5248
}
@@ -95,13 +91,13 @@ private fun <E : Throwable> recoverFromStackFrame(exception: E, continuation: Co
9591
* IllegalStateException
9692
* at foo
9793
* at kotlin.coroutines.resumeWith
98-
* at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
94+
* (Coroutine boundary)
9995
* at bar
10096
* ...real stackTrace...
10197
* caused by "IllegalStateException" (original one)
10298
*/
10399
private fun <E : Throwable> createFinalException(cause: E, result: E, resultStackTrace: ArrayDeque<StackTraceElement>): E {
104-
resultStackTrace.addFirst(ARTIFICIAL_FRAME)
100+
resultStackTrace.addFirst(artificialFrame("Coroutine boundary"))
105101
val causeTrace = cause.stackTrace
106102
val size = causeTrace.frameIndex(baseContinuationImplClassName)
107103
if (size == -1) {
@@ -191,7 +187,12 @@ private fun createStackTrace(continuation: CoroutineStackFrame): ArrayDeque<Stac
191187
return stack
192188
}
193189

194-
internal fun StackTraceElement.isArtificial() = className.startsWith(ARTIFICIAL_FRAME_PACKAGE_NAME)
190+
/**
191+
* @suppress
192+
*/
193+
@InternalCoroutinesApi
194+
public fun artificialFrame(message: String): StackTraceElement = java.lang.StackTraceElement("\b\b\b($message", "\b", "\b", -1)
195+
internal fun StackTraceElement.isArtificial() = className.startsWith("\b\b\b")
195196
private fun Array<StackTraceElement>.frameIndex(methodName: String) = indexOfFirst { methodName == it.className }
196197

197198
private fun StackTraceElement.elementWiseEquals(e: StackTraceElement): Boolean {
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
kotlinx.coroutines.RecoverableTestException
22
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferFromScope$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:109)
3-
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
3+
(Coroutine boundary)
44
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.sendInChannel(StackTraceRecoveryChannelsTest.kt:167)
55
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$sendWithContext$2.invokeSuspend(StackTraceRecoveryChannelsTest.kt:162)
66
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$sendFromScope$2.invokeSuspend(StackTraceRecoveryChannelsTest.kt:172)
77
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferFromScope$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:112)
88
Caused by: kotlinx.coroutines.RecoverableTestException
99
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferFromScope$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:109)
10-
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
10+
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)

kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testOfferWithContextWrapped.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
kotlinx.coroutines.RecoverableTestException
22
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferWithContextWrapped$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:98)
3-
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
3+
(Coroutine boundary)
44
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.sendInChannel(StackTraceRecoveryChannelsTest.kt:199)
55
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$sendWithContext$2.invokeSuspend(StackTraceRecoveryChannelsTest.kt:194)
66
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferWithContextWrapped$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:100)

kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testOfferWithCurrentContext.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
kotlinx.coroutines.RecoverableTestException
22
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferWithCurrentContext$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:86)
3-
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
3+
(Coroutine boundary)
44
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.sendInChannel(StackTraceRecoveryChannelsTest.kt:210)
55
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$sendWithContext$2.invokeSuspend(StackTraceRecoveryChannelsTest.kt:205)
66
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testOfferWithCurrentContext$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:89)
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
kotlinx.coroutines.RecoverableTestException
22
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testReceiveFromChannel$1$job$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:97)
3-
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
3+
(Coroutine boundary)
44
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.channelReceive(StackTraceRecoveryChannelsTest.kt:116)
55
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testReceiveFromChannel$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:101)
66
Caused by: kotlinx.coroutines.RecoverableTestException
77
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testReceiveFromChannel$1$job$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:97)
8-
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
8+
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
kotlinx.coroutines.RecoverableTestException
22
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testReceiveFromClosedChannel$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:110)
3-
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
3+
(Coroutine boundary)
44
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.channelReceive(StackTraceRecoveryChannelsTest.kt:116)
55
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testReceiveFromClosedChannel$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:111)
66
Caused by: kotlinx.coroutines.RecoverableTestException
77
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testReceiveFromClosedChannel$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:110)
8-
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
8+
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
kotlinx.coroutines.RecoverableTestCancellationException
22
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendFromScope$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:136)
3-
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
3+
(Coroutine boundary)
44
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.sendInChannel(StackTraceRecoveryChannelsTest.kt:167)
55
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$sendWithContext$2.invokeSuspend(StackTraceRecoveryChannelsTest.kt:162)
66
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$sendFromScope$2.invokeSuspend(StackTraceRecoveryChannelsTest.kt:172)
77
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendFromScope$1$deferred$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:126)
88
Caused by: kotlinx.coroutines.RecoverableTestCancellationException
99
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendFromScope$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:136)
10-
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
10+
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)

kotlinx-coroutines-core/jvm/test-resources/stacktraces/channels/testSendToChannel.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ java.util.concurrent.CancellationException: RendezvousChannel was cancelled
22
at kotlinx.coroutines.channels.AbstractChannel.cancel(AbstractChannel.kt:630)
33
at kotlinx.coroutines.channels.ReceiveChannel$DefaultImpls.cancel$default(Channel.kt:311)
44
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendToChannel$1$job$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:52)
5-
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
5+
(Coroutine boundary)
66
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.channelSend(StackTraceRecoveryChannelsTest.kt:73)
77
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendToChannel$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:56)
88
Caused by: java.util.concurrent.CancellationException: RendezvousChannel was cancelled
99
at kotlinx.coroutines.channels.AbstractChannel.cancel(AbstractChannel.kt:630)
1010
at kotlinx.coroutines.channels.ReceiveChannel$DefaultImpls.cancel$default(Channel.kt:311)
1111
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendToChannel$1$job$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:52)
12-
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
12+
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
kotlinx.coroutines.RecoverableTestException
22
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendToClosedChannel$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:43)
3-
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
3+
(Coroutine boundary)
44
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest.channelSend(StackTraceRecoveryChannelsTest.kt:74)
55
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendToClosedChannel$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:44)
66
Caused by: kotlinx.coroutines.RecoverableTestException
77
at kotlinx.coroutines.exceptions.StackTraceRecoveryChannelsTest$testSendToClosedChannel$1.invokeSuspend(StackTraceRecoveryChannelsTest.kt:43)
8-
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
8+
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
kotlinx.coroutines.RecoverableTestException
22
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:61)
33
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testEventLoopDispatcher$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:40)
4-
at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)
4+
(Coroutine boundary)
55
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$withContext$2.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:76)
66
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.doFastPath(StackTraceRecoveryResumeModeTest.kt:71)
77
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:62)
88
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testEventLoopDispatcher$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:40)
99
Caused by: kotlinx.coroutines.RecoverableTestException
1010
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest.testResumeModeFastPath(StackTraceRecoveryResumeModeTest.kt:61)
1111
at kotlinx.coroutines.exceptions.StackTraceRecoveryResumeModeTest$testEventLoopDispatcher$1.invokeSuspend(StackTraceRecoveryResumeModeTest.kt:40)
12-
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
12+
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)

0 commit comments

Comments
 (0)