Skip to content

Commit 8411dfd

Browse files
authored
Avoid false activation-after-resolution findings for overlapping resumes
1 parent 6fbc832 commit 8411dfd

3 files changed

Lines changed: 27 additions & 17 deletions

File tree

‎dd-java-agent/instrumentation-testing/src/main/java/datadog/trace/agent/test/scopediag/ContinuationRecord.java‎

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ public synchronized EnumSet<Failure> failures(Long rootWrittenNanos) {
140140
if (duplicateTerminalAttempt || !extraTerminals.isEmpty()) {
141141
failures.add(Failure.DOUBLE_FINISH);
142142
}
143-
if ((terminal != null && !failedActivations.isEmpty()) || resumedAfterTerminal()) {
143+
// Cleanup entry timestamps do not order resolution against concurrent successful resumes.
144+
if (terminal != null && !failedActivations.isEmpty()) {
144145
failures.add(Failure.ACTIVATE_AFTER_RESOLVE);
145146
}
146147
if (rootWrittenNanos != null
@@ -150,18 +151,6 @@ public synchronized EnumSet<Failure> failures(Long rootWrittenNanos) {
150151
return failures;
151152
}
152153

153-
private boolean resumedAfterTerminal() {
154-
if (terminal == null) {
155-
return false;
156-
}
157-
for (ScopeEvent r : resumes) {
158-
if (r.nanos > terminal.nanos) {
159-
return true;
160-
}
161-
}
162-
return false;
163-
}
164-
165154
/** {@code true} when capture and any resume/terminal happened on different threads. */
166155
public synchronized boolean threadHandoff() {
167156
if (capture == null) {

‎dd-java-agent/instrumentation-testing/src/test/java/datadog/trace/agent/test/scopediag/ScopeDiagnosticsReportTest.java‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,16 +122,19 @@ void multipleResolutionsAreFlaggedDouble() {
122122
}
123123

124124
@Test
125-
void activationAfterResolveIsFailure() {
125+
void successfulResumeAfterCleanupEntryIsNotActivationAfterResolve() {
126126
ContinuationRecord r = record(0, DDTraceId.from(14));
127-
r.setTerminalOrExtra(event(ScopeEvent.Type.RESOLVE_RELEASE, "pool-1", 2000));
127+
r.addResume(event(ScopeEvent.Type.ACTIVATE, "pool-1", 1500));
128128
r.addResume(event(ScopeEvent.Type.ACTIVATE, "pool-2", 3000));
129+
r.setTerminalOrExtra(event(ScopeEvent.Type.RESOLVE_FINISH, "pool-1", 2000));
129130

130131
ScopeDiagnosticsReport report = report(list(r), map());
131132

132-
assertEquals(1, report.activateAfterResolveCount());
133+
assertEquals(2, report.records().get(0).resumes().size());
134+
assertEquals(ContinuationStatus.FINISHED, report.records().get(0).status());
135+
assertEquals(0, report.activateAfterResolveCount());
133136
assertEquals(0, report.doubleCount());
134-
assertTrue(report.hasProblems());
137+
assertFalse(report.hasProblems());
135138
}
136139

137140
@Test

‎dd-java-agent/instrumentation-testing/src/test/java/datadog/trace/agent/test/scopediag/ScopeResolutionTest.java‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,24 @@ void nestedReleaseBelongsToTheScopeClose() {
5858
assertEquals(ContinuationStatus.FINISHED, ScopeDiagnostics.report().records().get(0).status());
5959
}
6060

61+
@Test
62+
void delayedSuccessfulResumeCallbackAfterCleanupIsNotRejected() {
63+
Object window = ScopeDiagnostics.recordingWindow();
64+
ScopeContinuationProbe.ResolveAttempt close = enter("cancelFromContinuedScopeClose", 1);
65+
ScopeContinuationProbe.onResolveExit(close, CANCELLED);
66+
long cleanupEntryNanos = ScopeDiagnostics.report().records().get(0).terminal().nanos;
67+
68+
// The resume succeeded during cleanup, but its exit callback arrives after cleanup's callback.
69+
ScopeDiagnostics.recordActivate(
70+
window, continuation, DDTraceId.from(1), 2, "op", (byte) 0, cleanupEntryNanos + 1);
71+
72+
ScopeDiagnosticsReport report = ScopeDiagnostics.report();
73+
assertEquals(1, report.records().get(0).resumes().size());
74+
assertEquals(ContinuationStatus.FINISHED, report.records().get(0).status());
75+
assertEquals(0, report.activateAfterResolveCount());
76+
assertResolvedOnce();
77+
}
78+
6179
@Test
6280
void overlappingLegitimateScopeClosesResolveOnce() {
6381
Object window = ScopeDiagnostics.recordingWindow();

0 commit comments

Comments
 (0)