Skip to content

Commit f2c2e7d

Browse files
adinauerclaude
andauthored
fix(otel): Avoid deadlock in SentryContextStorage.root() with virtual threads (#5234)
* fix(otel): Avoid deadlock in SentryContextStorage.root() with virtual threads SentryContextStorage.root() called SentryContextWrapper.wrap() which triggers scope.clone() and acquires locks. Under virtual threads, ReentrantLock.unlock() can re-enter root() via OpenTelemetry executor instrumentation on ForkJoinPool.execute(), causing a deadlock. Return the default OTel root context without wrapping. Scopes are resolved later via attach() or Sentry.getCurrentScopes(). Fixes GH-5226 Co-Authored-By: Claude <noreply@anthropic.com> * changelog --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent a7fc366 commit f2c2e7d

File tree

2 files changed

+10
-1
lines changed

2 files changed

+10
-1
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Fixes
6+
7+
- Fix deadlock in `SentryContextStorage.root()` with virtual threads and OpenTelemetry agent ([#5234](https://github.com/getsentry/sentry-java/pull/5234))
8+
39
## 8.37.0
410

511
### Fixes

sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryContextStorage.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ public Context current() {
4141

4242
@Override
4343
public Context root() {
44-
return SentryContextWrapper.wrap(ContextStorage.super.root());
44+
// Don't wrap() here — it triggers scope.clone() which acquires locks. Under virtual
45+
// threads, lock.unlock() can re-enter here via OpenTelemetry executor instrumentation, causing
46+
// a deadlock.
47+
return ContextStorage.super.root();
4548
}
4649
}

0 commit comments

Comments
 (0)