Skip to content

Commit 526162b

Browse files
committed
When swapping context stacks, restore full stack on original thread.
For other threads restore shallow copy, using parent and active scopes captured when the original context stack was swapped out.
1 parent f02c1d1 commit 526162b

File tree

3 files changed

+27
-10
lines changed

3 files changed

+27
-10
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ public Context swap(Context context) {
367367
ContinuableScope newScope;
368368
if (context instanceof ScopeContext) {
369369
// restore previously swapped context stack
370-
newStack = ((ScopeContext) context).restore();
370+
newStack = ((ScopeContext) context).restore(profilingContextIntegration);
371371
newScope = newStack.top;
372372
} else if (context != Context.root()) {
373373
// start a new stack and record the new context as active

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
import datadog.context.Context;
44
import datadog.context.ContextKey;
5+
import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration;
56
import javax.annotation.Nullable;
67

78
/** Wraps a {@link ScopeStack} as a {@link Context} so it can be swapped back later. */
89
final class ScopeContext implements Context {
910
private final Thread originalThread = Thread.currentThread();
1011
private final ScopeStack scopeStack;
12+
private final ContinuableScope parent;
13+
private final ContinuableScope active;
1114
private final Context context;
1215

1316
ScopeContext(ScopeStack scopeStack) {
@@ -16,12 +19,18 @@ final class ScopeContext implements Context {
1619

1720
private ScopeContext(ScopeStack scopeStack, Context context) {
1821
this.scopeStack = scopeStack;
22+
this.parent = scopeStack.parent();
23+
this.active = scopeStack.active();
1924
this.context = context;
2025
}
2126

22-
ScopeStack restore() {
23-
// take defensive copy of original scope stack when restoring on different thread
24-
return originalThread == Thread.currentThread() ? scopeStack : scopeStack.copy();
27+
ScopeStack restore(ProfilingContextIntegration profilingContextIntegration) {
28+
// restore full stack on original thread, for other threads restore shallow copy
29+
if (Thread.currentThread() == originalThread) {
30+
return scopeStack;
31+
} else {
32+
return new ScopeStack(profilingContextIntegration, parent, active);
33+
}
2534
}
2635

2736
@Nullable

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,27 @@ 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;
27+
/** Restore a shallow stack for async propagation purposes. */
28+
ScopeStack(
29+
ProfilingContextIntegration profilingContextIntegration,
30+
ContinuableScope parent,
31+
ContinuableScope active) {
32+
this(profilingContextIntegration);
33+
if (parent != null) {
34+
stack.push(parent);
35+
}
36+
top = active;
3337
}
3438

3539
ContinuableScope active() {
3640
// avoid attaching further spans to the root scope when it's been marked as overdue
3741
return top != overdueRootScope ? top : null;
3842
}
3943

44+
ContinuableScope parent() {
45+
return stack.peek();
46+
}
47+
4048
/** Removes and closes all scopes up to the nearest live scope */
4149
void cleanup() {
4250
ContinuableScope curScope = top;

0 commit comments

Comments
 (0)