Skip to content

Commit c83ce0e

Browse files
committed
Take defensive copy of parent scope stack when closing nested coroutines
1 parent 0698839 commit c83ce0e

File tree

8 files changed

+43
-16
lines changed

8 files changed

+43
-16
lines changed

dd-java-agent/instrumentation/kotlin-coroutines/src/main/java/datadog/trace/instrumentation/kotlin/coroutines/ScopeStateCoroutineContext.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ public void restoreThreadContext(
3939

4040
@Override
4141
public ScopeState updateThreadContext(@NotNull final CoroutineContext coroutineContext) {
42-
final ScopeState oldScopeState = AgentTracer.get().newScopeState();
43-
oldScopeState.fetchFromActive();
42+
final ScopeState oldScopeState = AgentTracer.get().oldScopeState();
4443

4544
final Job coroutine = CoroutineContextHelper.getJob(coroutineContext);
4645
final ScopeStateCoroutineContextItem contextItem = contextItemPerCoroutine.get(coroutine);
@@ -53,22 +52,21 @@ public ScopeState updateThreadContext(@NotNull final CoroutineContext coroutineC
5352

5453
/** If there's a context item for the coroutine then try to close it */
5554
public void maybeCloseScopeAndCancelContinuation(final Job coroutine, final Job parent) {
56-
final ScopeStateCoroutineContextItem contextItem = contextItemPerCoroutine.get(coroutine);
55+
final ScopeStateCoroutineContextItem contextItem = contextItemPerCoroutine.remove(coroutine);
5756
if (contextItem != null) {
5857
ScopeState currentThreadScopeState = null;
5958
if (parent != null) {
6059
final ScopeStateCoroutineContextItem parentItem = contextItemPerCoroutine.get(parent);
6160
if (parentItem != null) {
62-
currentThreadScopeState = parentItem.getScopeState();
61+
// take defensive copy of parent scope stack
62+
currentThreadScopeState = parentItem.copyScopeState();
6363
}
6464
}
6565
if (currentThreadScopeState == null) {
66-
currentThreadScopeState = AgentTracer.get().newScopeState();
67-
currentThreadScopeState.fetchFromActive();
66+
currentThreadScopeState = AgentTracer.get().oldScopeState();
6867
}
6968

7069
contextItem.maybeCloseScopeAndCancelContinuation();
71-
contextItemPerCoroutine.remove(coroutine);
7270

7371
currentThreadScopeState.activate();
7472
}
@@ -116,8 +114,8 @@ public ScopeStateCoroutineContextItem() {
116114
coroutineScopeState = AgentTracer.get().newScopeState();
117115
}
118116

119-
public ScopeState getScopeState() {
120-
return coroutineScopeState;
117+
public ScopeState copyScopeState() {
118+
return coroutineScopeState.copy();
121119
}
122120

123121
public void activate() {

dd-java-agent/instrumentation/zio/zio-2.0/src/main/java/datadog/trace/instrumentation/zio/v2_0/FiberContext.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ public void onSuspend() {
5252
}
5353

5454
public void onResume() {
55-
this.oldState = AgentTracer.get().newScopeState();
56-
this.oldState.fetchFromActive();
55+
this.oldState = AgentTracer.get().oldScopeState();
5756

5857
this.state.activate();
5958

dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,11 @@ public EndpointTracker onRootSpanStarted(AgentSpan root) {
294294
return null;
295295
}
296296

297+
@Override
298+
public ScopeState oldScopeState() {
299+
return scopeManager.oldScopeState();
300+
}
301+
297302
@Override
298303
public ScopeState newScopeState() {
299304
return scopeManager.newScopeState();

dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,14 @@ ScopeStack scopeStack() {
349349
return this.tlsScopeStack.get();
350350
}
351351

352+
@Override
353+
public ScopeState oldScopeState() {
354+
return new ContinuableScopeState(tlsScopeStack.get());
355+
}
356+
352357
@Override
353358
public ScopeState newScopeState() {
354-
return new ContinuableScopeState();
359+
return new ContinuableScopeState(tlsScopeStack.initialValue());
355360
}
356361

357362
@Override
@@ -371,17 +376,20 @@ public Context swap(Context context) {
371376
}
372377

373378
private class ContinuableScopeState implements ScopeState {
379+
private final ScopeStack localScopeStack;
374380

375-
private ScopeStack localScopeStack = tlsScopeStack.initialValue();
381+
ContinuableScopeState(ScopeStack scopeStack) {
382+
this.localScopeStack = scopeStack;
383+
}
376384

377385
@Override
378386
public void activate() {
379387
tlsScopeStack.set(localScopeStack);
380388
}
381389

382390
@Override
383-
public void fetchFromActive() {
384-
localScopeStack = tlsScopeStack.get();
391+
public ScopeState copy() {
392+
return new ContinuableScopeState(localScopeStack.copy());
385393
}
386394
}
387395

dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeStack.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ final class ScopeStack {
2424
this.profilingContextIntegration = profilingContextIntegration;
2525
}
2626

27+
ScopeStack copy() {
28+
ScopeStack copy = new ScopeStack(profilingContextIntegration);
29+
copy.stack.addAll(stack);
30+
copy.top = top;
31+
copy.overdueRootScope = overdueRootScope;
32+
return copy;
33+
}
34+
2735
ContinuableScope active() {
2836
// avoid attaching further spans to the root scope when it's been marked as overdue
2937
return top != overdueRootScope ? top : null;

internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,11 @@ public AgentSpanContext notifyExtensionStart(Object event) {
638638
@Override
639639
public void notifyExtensionEnd(AgentSpan span, Object result, boolean isError) {}
640640

641+
@Override
642+
public ScopeState oldScopeState() {
643+
return null;
644+
}
645+
641646
@Override
642647
public ScopeState newScopeState() {
643648
return null;

internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeState.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
public interface ScopeState {
44
void activate();
55

6-
void fetchFromActive();
6+
ScopeState copy();
77
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package datadog.trace.bootstrap.instrumentation.api;
22

33
public interface ScopeStateAware {
4+
/** @return The old connected scope stack */
5+
ScopeState oldScopeState();
6+
7+
/** @return A new disconnected scope stack */
48
ScopeState newScopeState();
59
}

0 commit comments

Comments
 (0)