-
Notifications
You must be signed in to change notification settings - Fork 937
Description
Describe the bug
The Context.makeCurrent() method attaches the current context to a ThreadLocal (via ContextStorage) and returns a Scope.
The API design relies heavily on the caller to manually invoke Scope.close() to detach the context. If makeCurrent() is used without a strict try-with-resources block, and an exception occurs during execution, the Scope.close() call is skipped.
This results in Context Leakage: The thread remains "polluted" with the stale Context (and Trace ID). In a thread-pool environment, subsequent unrelated requests processed by this thread will inherit the incorrect Trace ID, leading to broken distributed traces.
Steps to reproduce
-
Create a context: Context ctx = Context.root().with(key, value);
-
Invoke ctx.makeCurrent() without using try-with-resources.
-
Simulate a RuntimeException immediately after attachment.
-
Catch the exception in an outer block.
-
Check Context.current() on the same thread.
What did you expect to see?
Context.current() should revert to Context.root() (or the previous parent) after the operation fails, ensuring the thread is clean.
What did you see instead?
Context.current() still returns the stale ctx. The ThreadLocal was not cleared because Scope.close() was never executed.
What version and what artifacts are you using?
Artifacts: io.opentelemetry:opentelemetry-context
Version: main
Environment
Runtime: Any Java environment using Thread Pools
Additional context
Location: io.opentelemetry.context.Context.java (Line 213: makeCurrent()).
Reference Code:
@MustBeClosed
default Scope makeCurrent() {
return ContextStorage.get().attach(this);
}