Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ArrayIndexOutOfBoundsException from MutableSpan #1384

Closed
karkum opened this issue May 10, 2023 · 8 comments · Fixed by #1434
Closed

ArrayIndexOutOfBoundsException from MutableSpan #1384

karkum opened this issue May 10, 2023 · 8 comments · Fixed by #1434
Assignees
Labels

Comments

@karkum
Copy link

karkum commented May 10, 2023

Describe the Bug

When adding tags to an ongoing span, we occasionally see the following exception:

java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4
  at brave.handler.MutableSpan.tag(MutableSpan.java:883)
  at brave.RealSpan.tag(RealSpan.java:112)
  at brave.SpanCustomizerShield.tag(SpanCustomizerShield.java:35)
  at brave.CurrentSpanCustomizer.tag(CurrentSpanCustomizer.java:41)

I believe this occurs in rare race-conditions in which some tags are removed while others are being added. I will attempt to reproduce this with a test, but I'm not having any luck so far. Wanted to create this issue and see if others are seeing anything similar.

@karkum karkum added the bug label May 10, 2023
@Saravana-PS
Copy link

Saravana-PS commented May 14, 2023

Hey @karkum , I would like to work on this issue. Can you assign it on me?

@codefromthecrypt codefromthecrypt transferred this issue from openzipkin/zipkin Dec 15, 2023
@SomayajuluSharma
Copy link

Hello @karkum is anyone working in this?

@codefromthecrypt
Copy link
Member

I think @reta is looking to remove synchronized for a different concurrent pattern, so whatever is missing here probably a good time to fix it without resurrecting synchronized ;)

@codefromthecrypt
Copy link
Member

so currently it should be guarded by this in RealSpan

  @Override public Span tag(String key, String value) {
    synchronized (state) {
      state.tag(key, value);
    }
    return this;
  }

ScopedSpan is unguarded, but that's also documented as not thread safe.

The culprit is Tag.tag which accesses the mutable span without synchronizing it. @reta lemme know if you want me to add synchronized to undo later, or if you feel you're close to removing synchronized. I kindof lean towards doing synchronized and releasing a patch to fix it..

@reta reta self-assigned this Mar 31, 2024
@reta
Copy link
Contributor

reta commented Mar 31, 2024

@codefromthecrypt just picked #1426 up, will address this issue as well, thanks a lot for figuring out the cause (and the fix).

@reta
Copy link
Contributor

reta commented Mar 31, 2024

I kindof lean towards doing synchronized and releasing a patch to fix it..

I was looking into Tag.tag, particularly this snippet:

   if (span instanceof SpanCustomizer) {
      ((SpanCustomizer) span).tag(key, value);
    } else if (span instanceof MutableSpan) {
      ((MutableSpan) span).tag(key, value);
    }

I think it is rather difficult to fix it it just with synchronized or any kind of locking here: yes, we could synchronize over span instance (I think this is your idea), but the MutableSpan.tag could still be accessed directly and this access will be unguarded. Does it make sense? Thank you.

@codefromthecrypt
Copy link
Member

might have been a red herring.. for example, a user cannot access the mutable span until it is inside a span handler, which should already be locked at that point. sorry if I led you down the wrong path.

Basically we don't want to lock fine grained mutablespan as it will explode overhead in ways maybe our benchmarks aren't written to show. If we locked internally in mutablespan, there are existing code which iterate through all things and update many things. So, better to change nothing until sure.

@reta
Copy link
Contributor

reta commented Apr 2, 2024

Thanks @codefromthecrypt

might have been a red herring.. for example, a user cannot access the mutable span until it is inside a span handler, which should already be locked at that point. sorry if I led you down the wrong path.

Aha I see, will look more closely into it (definitely not suggesting we locked internally in mutablespan at the moment, I agree)

codefromthecrypt pushed a commit that referenced this issue Apr 10, 2024
The current codebase carefully synchronizes all access to MutableSpan
where there can be concurrent use. We missed a spot where Tag.tag is not
synchronizing access. The only other place we don't guard is ScopedSpan,
which is documented explicitly as not thread safe.

Fixes #1384

Signed-off-by: Adrian Cole <adrian@tetrate.io>
codefromthecrypt pushed a commit that referenced this issue Apr 10, 2024
The current codebase carefully synchronizes all access to MutableSpan
where there can be concurrent use. We missed a spot where Tag.tag is not
synchronizing access. The only other place we don't guard is ScopedSpan,
which is documented explicitly as not thread safe.

Fixes #1384

Signed-off-by: Adrian Cole <adrian@tetrate.io>
@reta reta assigned codefromthecrypt and unassigned reta Apr 10, 2024
codefromthecrypt added a commit that referenced this issue Apr 11, 2024
The current codebase carefully synchronizes all access to MutableSpan
where there can be concurrent use. We missed a spot where Tag.tag is not
synchronizing access. The only other place we don't guard is ScopedSpan,
which is documented explicitly as not thread safe.

Fixes #1384

Signed-off-by: Adrian Cole <adrian@tetrate.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants