diff --git a/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java b/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java index 5f3777ea44c..71c0a8b7661 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java @@ -367,7 +367,7 @@ public Context swap(Context context) { ContinuableScope newScope; if (context instanceof ScopeContext) { // restore previously swapped context stack - newStack = ((ScopeContext) context).scopeStack; + newStack = ((ScopeContext) context).restore(); newScope = newStack.top; } else if (context != Context.root()) { // start a new stack and record the new context as active diff --git a/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeContext.java b/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeContext.java index 2f3d6dc5aab..9fecf26976c 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeContext.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeContext.java @@ -6,7 +6,8 @@ /** Wraps a {@link ScopeStack} as a {@link Context} so it can be swapped back later. */ final class ScopeContext implements Context { - final ScopeStack scopeStack; + private final Thread originalThread = Thread.currentThread(); + private final ScopeStack scopeStack; private final Context context; ScopeContext(ScopeStack scopeStack) { @@ -18,6 +19,11 @@ private ScopeContext(ScopeStack scopeStack, Context context) { this.context = context; } + ScopeStack restore() { + // take defensive copy of original scope stack when restoring on different thread + return originalThread == Thread.currentThread() ? scopeStack : scopeStack.copy(); + } + @Nullable @Override public T get(ContextKey key) {