Skip to content

Fix jedis-4.x-plugin double-stopping the span stack on Redis exceptions - #829

Merged
wu-sheng merged 1 commit into
apache:mainfrom
Shaoliangchen:fix/jedis-4x-plugin-double-stopspan
Sep 16, 2026
Merged

wu-sheng merged 1 commit into
apache:mainfrom
Shaoliangchen:fix/jedis-4x-plugin-double-stopspan

Conversation

@Shaoliangchen

Copy link
Copy Markdown
Contributor

What changed

AbstractConnectionInterceptor.handleMethodException() called ContextManager.stopSpan(span)
explicitly, but afterMethod() always runs afterwards too (InstMethodsInter invokes it in a
finally block on every path, including exceptions) and stops the same span again. The second
stopSpan() pops whatever is now on top of the stack instead — typically the caller's
entry/local span — corrupting the trace for the rest of the request.

beforeMethod() also dereferenced the per-Connection dynamic field without a null check. When
it is null (observed for some pooled/recycled connections not captured by the constructor
interceptor), this throws before createExitSpan() runs, so afterMethod()'s stopSpan() again
pops a span that was never pushed by this interceptor.

Fix

  • Only log the error in handleMethodException() (matching jedis-2.x-3.x-plugin's safe
    behavior) instead of stopping the span a second time.
  • Fall back to an "unknown" peer when the dynamic field is null so the exit span is always
    pushed and the stack stays balanced.

Testing

  • ./mvnw checkstyle:check -pl apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin -am
  • ./mvnw test -pl apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin -am — BUILD SUCCESS

Resolves apache/skywalking#14085

AbstractConnectionInterceptor.handleMethodException() called
ContextManager.stopSpan(span) explicitly, but afterMethod() always runs
afterwards too (InstMethodsInter invokes it in a finally block on every
path, including exceptions) and stops the same span again. The second
stopSpan() pops whatever is now on top of the stack instead - typically
the caller's entry/local span - corrupting the trace for the rest of
the request.

beforeMethod() also dereferenced the per-Connection dynamic field
without a null check. When it is null (observed for some pooled or
recycled connections not captured by the constructor interceptor),
this throws before createExitSpan() runs, so afterMethod()'s stopSpan()
again pops a span that was never pushed by this interceptor.

Fix: only log the error in handleMethodException() (matching
jedis-2.x-3.x-plugin's safe behavior) and fall back to an "unknown"
peer when the dynamic field is null so the exit span is always pushed
and the stack stays balanced.

Resolves apache/skywalking#14085
@wu-sheng wu-sheng added this to the 9.8.0 milestone Sep 16, 2026
@wu-sheng wu-sheng added bug Something isn't working plugin labels Sep 16, 2026
@wu-sheng
wu-sheng merged commit 47ff1e8 into apache:main Sep 16, 2026
269 of 314 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working plugin

Projects

None yet

2 participants