Skip to content

Commit 8a3753d

Browse files
committed
Preserve a frame with source code location when sanitizing traces
Fixes #1437
1 parent fa30140 commit 8a3753d

File tree

2 files changed

+29
-20
lines changed

2 files changed

+29
-20
lines changed

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

+27-20
Original file line numberDiff line numberDiff line change
@@ -477,33 +477,40 @@ internal object DebugProbesImpl {
477477

478478
/*
479479
* Trim intervals of internal methods from the stacktrace (bounds are excluded from trimming)
480-
* E.g. for sequence [e, i1, i2, i3, e, i4, e, i5, i6, e7]
480+
* E.g. for sequence [e, i1, i2, i3, e, i4, e, i5, i6, i7]
481481
* output will be [e, i1, i3, e, i4, e, i5, i7]
482+
*
483+
* If an interval of internal methods ends in a synthetic method, the last non-synthetic method in that interval
484+
* will also be included.
482485
*/
483486
val result = ArrayList<StackTraceElement>(size - probeIndex + 1)
484487
result += createArtificialFrame(ARTIFICIAL_FRAME_MESSAGE)
485-
var includeInternalFrame = true
486-
for (i in (probeIndex + 1) until size - 1) {
487-
val element = stackTrace[i]
488-
if (!element.isInternalMethod) {
489-
includeInternalFrame = true
490-
result += element
491-
continue
492-
}
493-
494-
if (includeInternalFrame) {
495-
result += element
496-
includeInternalFrame = false
497-
} else if (stackTrace[i + 1].isInternalMethod) {
498-
continue
488+
var i = probeIndex + 1
489+
while (i < size) {
490+
if (stackTrace[i].isInternalMethod) {
491+
result += stackTrace[i] // we include the boundary of the span in any case
492+
// first index past the end of the span of internal methods that starts from `i`
493+
var j = i + 1
494+
while (j < size && stackTrace[j].isInternalMethod) {
495+
j += 1
496+
}
497+
// index of the last non-synthetic internal methods in this span, or `i` if there are no such methods
498+
var k = j - 1
499+
while (k > i && stackTrace[k].fileName == null) {
500+
k -= 1
501+
}
502+
if (k > i && k < j - 1) {
503+
/* there are synthetic internal methods at the end of this span, but there is a non-synthetic method
504+
ofter `i`, so we include it. */
505+
result += stackTrace[k]
506+
}
507+
result += stackTrace[j - 1] // we include the other boundary of this span in any case, too
508+
i = j
499509
} else {
500-
result += element
501-
includeInternalFrame = true
510+
result += stackTrace[i]
511+
i += 1
502512
}
503-
504513
}
505-
506-
result += stackTrace[size - 1]
507514
return result
508515
}
509516

kotlinx-coroutines-debug/test/SanitizedProbesTest.kt

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class SanitizedProbesTest : DebugTestBase() {
6363
"\t(Coroutine creation stacktrace)\n" +
6464
"\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" +
6565
"\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:23)\n" +
66+
"\tat kotlinx.coroutines.BuildersKt__Builders_commonKt.async\$default(Builders.common.kt)\n" +
6667
"\tat kotlinx.coroutines.BuildersKt.async\$default(Unknown Source)\n" +
6768
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.createActiveDeferred(SanitizedProbesTest.kt:62)\n" +
6869
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.access\$createActiveDeferred(SanitizedProbesTest.kt:16)\n" +
@@ -91,6 +92,7 @@ class SanitizedProbesTest : DebugTestBase() {
9192
"\t(Coroutine creation stacktrace)\n" +
9293
"\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" +
9394
"\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:25)\n" +
95+
"\tat kotlinx.coroutines.BuildersKt__Builders_commonKt.launch\$default(Builders.common.kt)\n" +
9496
"\tat kotlinx.coroutines.BuildersKt.launch\$default(Unknown Source)\n" +
9597
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.launchSelector(SanitizedProbesTest.kt:100)\n" +
9698
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.access\$launchSelector(SanitizedProbesTest.kt:16)\n" +

0 commit comments

Comments
 (0)