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

Fix misuses of CopyOnWriteArrayList #4247

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
### Fixes

- Add support for setting in-app-includes/in-app-excludes via AndroidManifest.xml ([#4240](https://github.com/getsentry/sentry-java/pull/4240))
- Avoid unnecessary copies and ensure thread-safety when using `CopyOnWriteArrayList` ([#4247](https://github.com/getsentry/sentry-java/pull/4247))
- This affects in particular `SentryTracer.getLatestActiveSpan` which would have previously unnecessarily copied all children spans, with high impact on memory usage

### Features

Expand Down
2 changes: 1 addition & 1 deletion sentry/src/main/java/io/sentry/Scope.java
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ public void removeContexts(final @NotNull String key) {
@NotNull
@Override
public List<Attachment> getAttachments() {
return new CopyOnWriteArrayList<>(attachments);
return attachments;
Copy link
Member Author

Choose a reason for hiding this comment

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

It is not necessary to copy here, as we are already using a CopyOnWriteArrayList

}

/**
Expand Down
35 changes: 19 additions & 16 deletions sentry/src/main/java/io/sentry/SentryTracer.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import io.sentry.util.AutoClosableReentrantLock;
import io.sentry.util.Objects;
import io.sentry.util.SpanUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
Expand Down Expand Up @@ -155,7 +154,10 @@ private void onDeadlineTimeoutReached() {
// abort all child-spans first, this ensures the transaction can be finished,
// even if waitForChildren is true
// iterate in reverse order to ensure leaf spans are processed before their parents
@NotNull final ListIterator<Span> iterator = children.listIterator(children.size());
Copy link
Member Author

Choose a reason for hiding this comment

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

This is not thread safe, the list could change size after we create the iterator

@NotNull final ListIterator<Span> iterator = this.children.listIterator();
while (iterator.hasNext()) {
iterator.next();
}
Comment on lines +158 to +160
Copy link
Member Author

Choose a reason for hiding this comment

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

Need to do it this way as there's no other way to get a reverse iterator in a thread-safe manner

while (iterator.hasPrevious()) {
@NotNull final Span span = iterator.previous();
span.setSpanFinishedCallback(null);
Expand Down Expand Up @@ -677,14 +679,13 @@ private void updateBaggageValues(final @NotNull Baggage baggage) {
}

private boolean hasAllChildrenFinished() {
final List<Span> spans = new ArrayList<>(this.children);
if (!spans.isEmpty()) {
for (final Span span : spans) {
// This is used in the spanFinishCallback, when the span isn't finished, but has a finish
// date
if (!span.isFinished() && span.getFinishDate() == null) {
return false;
}
@NotNull final ListIterator<Span> iterator = this.children.listIterator();
while (iterator.hasNext()) {
@NotNull final Span span = iterator.previous();
// This is used in the spanFinishCallback, when the span isn't finished, but has a finish
// date
if (!span.isFinished() && span.getFinishDate() == null) {
return false;
}
}
return true;
Expand Down Expand Up @@ -909,12 +910,14 @@ public void setName(@NotNull String name, @NotNull TransactionNameSource transac

@Override
public @Nullable ISpan getLatestActiveSpan() {
final List<Span> spans = new ArrayList<>(this.children);
if (!spans.isEmpty()) {
for (int i = spans.size() - 1; i >= 0; i--) {
if (!spans.get(i).isFinished()) {
return spans.get(i);
}
@NotNull final ListIterator<Span> iterator = this.children.listIterator();
while (iterator.hasNext()) {
iterator.next();
}
while (iterator.hasPrevious()) {
@NotNull final Span span = iterator.previous();
if (!span.isFinished()) {
return span;
}
}
return null;
Expand Down
Loading