Skip to content

Fix directoryDownload cancel leak#6875

Merged
RanVaknin merged 5 commits into
masterfrom
rvaknin/fix-directory-download-cancel-leak
Apr 28, 2026
Merged

Fix directoryDownload cancel leak#6875
RanVaknin merged 5 commits into
masterfrom
rvaknin/fix-directory-download-cancel-leak

Conversation

@RanVaknin
Copy link
Copy Markdown
Collaborator

@RanVaknin RanVaknin commented Apr 17, 2026

When a DirectoryDownload (or DirectoryUpload) future is cancelled or completed exceptionally, AsyncBufferingSubscriber cancels in flight file transfer futures but does not cancel the upstream Subscription.

This means the listObjectsV2 paginator continues delivering objects, and new file downloads continue to be started after the user has cancelled the operation.

This change adds subscription.cancel() to the whenComplete handler so that cancellation stops the entire pipeline of both inflight transfers and new work from the upstream publisher.

Conforms to Reactive Streams spec:

6 A Subscriber MUST call Subscription.cancel() if the Subscription is no longer needed.

@RanVaknin RanVaknin requested a review from a team as a code owner April 17, 2026 18:26
subscriber.onNext("item");

verify(mockSubscription, times(1)).cancel();
verify(mockSubscription, times(2)).cancel();
Copy link
Copy Markdown
Collaborator Author

@RanVaknin RanVaknin Apr 17, 2026

Choose a reason for hiding this comment

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

subscription.cancel() now exists in two codepaths:

  1. The existing codepath within onNext() catch block.
  2. The new addition in future.whenComplete()

Flow:

- onNext()
-- catch
-- subscription.cancel()
-- onError()

- onError()
-- completes exceptionally
-- future.whenCompleted()
-- subscription.cancel() // <-- new addition

I believe this is safe to call twice because:

5 Subscription.cancel MUST respect the responsivity of its caller by returning in a timely manner, MUST be idempotent and MUST be thread-safe.

Note: the codepath which the new addition solves is when the cancellation signal comes from outside of the pub/sub pipeline. If a user aborts the operation by cancelling the DirectoryDownload completion future directly, neither onNext nor onError are involved. The whenComplete handler is the only place that reacts to this external cancellation.

@RanVaknin RanVaknin force-pushed the rvaknin/fix-directory-download-cancel-leak branch from 8f2c15c to 58d296f Compare April 21, 2026 21:19
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
34 Security Hotspots
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@RanVaknin RanVaknin added this pull request to the merge queue Apr 28, 2026
Merged via the queue into master with commit ae7047c Apr 28, 2026
47 of 51 checks passed
@github-actions
Copy link
Copy Markdown

This pull request has been closed and the conversation has been locked. Comments on closed PRs are hard for our team to see. If you need more assistance, please open a new issue that references this one.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Apr 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants