Skip to content

Ensure byte string transformers clean up on every stage stop#1154

Merged
He-Pin merged 1 commit into
apache:mainfrom
He-Pin:fix-byte-string-transformer-cleanup
Jul 10, 2026
Merged

Ensure byte string transformers clean up on every stage stop#1154
He-Pin merged 1 commit into
apache:mainfrom
He-Pin:fix-byte-string-transformer-cleanup

Conversation

@He-Pin

@He-Pin He-Pin commented Jul 10, 2026

Copy link
Copy Markdown
Member

Motivation

PR #1142 added cleanup for byte string transformers, but the stage marked itself finished as soon as finish returned. If the final ByteString was waiting for downstream demand and downstream cancelled, postStop observed the finished flag and skipped cleanup.

The current Deflate and Gzip finish path already closes its Deflater before returning, so this follow-up hardens the generic stage lifecycle rather than claiming a second normal-path native leak.

Modification

Remove the finished flag and invoke the cleanup callback unconditionally from postStop, making cleanup the single finalizer for normal completion, failure, cancellation, and materializer shutdown.

Add directional StreamUtils tests for normal completion and for cancellation while a final emission is pending.

Result

Transformer resources are finalized on every stage termination path. The only production cleanup callback is idempotent, so normal completion still calls Deflater.end exactly once.

References

Refs #1133

Refs #1142

Motivation:
A byte string transformer marked itself finished before a pending final emission was delivered, so downstream cancellation in that window skipped cleanup.

Modification:
Treat cleanup as the stage finalizer by invoking it unconditionally from postStop, and add directional tests for normal completion and cancellation while the final emission is pending.

Result:
All stage termination paths release transformer resources without relying on a fragile finished flag. Existing compressor cleanup remains safe because it is idempotent.

Tests:
- sbt "http-core / Test / testOnly org.apache.pekko.http.impl.util.StreamUtilsSpec": 7 passed
- sbt "http-tests / Test / testOnly org.apache.pekko.http.scaladsl.coding.DeflateSpec org.apache.pekko.http.scaladsl.coding.GzipSpec": 54 passed
- sbt checkCodeStyle: passed
- sbt headerCreateAll and +headerCheckAll: passed
- scalafmt --list --mode diff-ref=origin/main: passed
- sbt sortImports: environment failure, Scalafix/scala.meta NoSuchMethodError
- sbt validatePullRequest: not run locally per maintainer request; delegated to CI

References:
Refs apache#1133; follow-up to apache#1142
@He-Pin He-Pin requested a review from pjfanning July 10, 2026 20:04
@He-Pin He-Pin added this to the 2.0.0-M2 milestone Jul 10, 2026

@pjfanning pjfanning left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm

@He-Pin He-Pin merged commit 18796ca into apache:main Jul 10, 2026
6 checks passed
@He-Pin He-Pin deleted the fix-byte-string-transformer-cleanup branch July 10, 2026 20:20
@pjfanning

Copy link
Copy Markdown
Member

@He-Pin can you back port this to 1.4.x branch?

He-Pin added a commit that referenced this pull request Jul 11, 2026
Motivation:
A byte string transformer marked itself finished before a pending final emission was delivered, so downstream cancellation in that window skipped cleanup.

Modification:
Treat cleanup as the stage finalizer by invoking it unconditionally from postStop, and add directional tests for normal completion and cancellation while the final emission is pending.

Result:
All stage termination paths release transformer resources without relying on a fragile finished flag. Existing compressor cleanup remains safe because it is idempotent.

Tests:
- sbt "http-core / Test / testOnly org.apache.pekko.http.impl.util.StreamUtilsSpec": 7 passed
- sbt "http-tests / Test / testOnly org.apache.pekko.http.scaladsl.coding.DeflateSpec org.apache.pekko.http.scaladsl.coding.GzipSpec": 54 passed
- sbt checkCodeStyle: passed
- sbt headerCreateAll and +headerCheckAll: passed
- scalafmt --list --mode diff-ref=origin/main: passed
- sbt sortImports: environment failure, Scalafix/scala.meta NoSuchMethodError
- sbt validatePullRequest: not run locally per maintainer request; delegated to CI

References:
Refs #1133; follow-up to #1142
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.

2 participants