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

Remove subsegments lock #278

Merged
merged 5 commits into from
Apr 22, 2021
Merged

Conversation

anuraaga
Copy link
Contributor

@anuraaga anuraaga commented Apr 21, 2021

Issue #, if available: Fixes #276

Description of changes:
Since we lock all access to the segment now, the subsegments lock is mostly not necessary. The only pattern it was needed for is user code doing something like

getSubsegmentsLock().lock()
getSubsegments().add(segment) // Not addSubsegment
unlock()

But it's basically impossible to make code deadlock-free when returning locks to unknown code and is basically a forbidden practice in Java. I think it's best we just hope no one is doing this, and if someone is and tells us, we recommend the unfortunate code change of switching to addSubsegment.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Copy link
Contributor

@steven-aerts steven-aerts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this introduces #181 again.

@@ -98,14 +92,8 @@ private boolean stream(Entity entity, Emitter emitter) {
//Gather children and in the condition they are ready to stream, add them to the streamable list.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think/fear a different race condition just moved 2 lines up now by removing the subsegmentLock. And you will hit #181 again.

As the copy of entity.getSubsegments() is taken outside the protected region.
So it is possible that an entity is added while the subsegment list is being copied what can/will result in a ConcurrentModificationException being thrown.

Possible solutions I see:

  • Make the collection returned by getSubsegments thread safe
  • Let getSubsegments return an (immutable) copy of the list (or provide another function which does).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for noticing this @steven-aerts - I've updated to return a copy

Copy link
Contributor

@willarmiros willarmiros left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we can cook up a test to try to reproduce #276? I'm imagining something with 2 threads, forcing the deadlock with Thread.sleep where needed. If it's too flaky or too much work that's ok, but would be nice to have.

@Override
public List<Subsegment> getSubsegmentsCopy() {
synchronized (lock) {
return new ArrayList<>(subsegments);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we return an UnmodifiableCollection of the subsegments list here? Or do we intentionally want to return a snapshot of the current subsegments at copying time that is not updated with new subsegments?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I think it is more clear, but won't mind if the proposed behavior is kept.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wrapping the subsegments won't solve the thread safety possibility, it needs to be a copy. I could also wrap the copy with Unmodifiable but I don't think we really need to for copies.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok fair enough, yeah I guess doing an UnmodifiableCollection would still allow the user to mutate the individual subsegments.

Copy link
Contributor

@steven-aerts steven-aerts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we can cook up a test to try to reproduce #276? I'm imagining something with 2 threads, forcing the deadlock with Thread.sleep where needed. If it's too flaky or too much work that's ok, but would be nice to have.

@willarmiros I tried when I created this ticket but was not able to do so. Only saw it in live code :-( .

@Override
public List<Subsegment> getSubsegmentsCopy() {
synchronized (lock) {
return new ArrayList<>(subsegments);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I think it is more clear, but won't mind if the proposed behavior is kept.

Copy link
Contributor

@willarmiros willarmiros left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@willarmiros willarmiros merged commit adfb395 into aws:master Apr 22, 2021
willarmiros pushed a commit to willarmiros/aws-xray-sdk-java that referenced this pull request Aug 13, 2022
wangzlei pushed a commit that referenced this pull request Aug 22, 2022
* Revert "Don't lock segment from subsegment (#306)"

This reverts commit d5ccae2.

* Revert "Keep track of emitted in emitter. (#279)"

This reverts commit d66d69a.

* Revert "Remove subsegments lock (#278)"

This reverts commit adfb395.

* Revert "Lock all accesses to entities. (#250)"

This reverts commit f0a3b3a.

* add back errorprone annotations

* fixed shouldPropagate

* added back getSubsegmentsCopy

* added back compareAndSetEmitted

* whitespace fix
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Deadlock when streaming some subsegments when parent is still open
3 participants