Skip to content

Ensure proper release of data buffers and handle output stream closure in template processing#4

Merged
JohnNiang merged 1 commit intomainfrom
bug/output-stream-may-not-be-closed
Nov 6, 2025
Merged

Ensure proper release of data buffers and handle output stream closure in template processing#4
JohnNiang merged 1 commit intomainfrom
bug/output-stream-may-not-be-closed

Conversation

@JohnNiang
Copy link
Copy Markdown
Member

Recently, we have detected some memory leak reports. That only happens at connection closed unexpectedly.

This PR ensures proper release of data buffers and handle output stream closure in template processing.

2025-11-05T14:24:45.108+08:00 ERROR 1254622 --- [loomBoundedElastic-33650] io.netty.util.ResourceLeakDetector : LEAK: ByteBuf.release() was not called before it's garbage-collected. See https://netty.io/wiki/reference-counted-objects.html for more information.
Recent access records:
#1:
        io.netty.buffer.AdvancedLeakAwareByteBuf.writeBytes(AdvancedLeakAwareByteBuf.java:617)
        org.springframework.core.io.buffer.NettyDataBuffer.write(NettyDataBuffer.java:186)
        org.springframework.core.io.buffer.NettyDataBuffer.write(NettyDataBuffer.java:40)
        org.springframework.core.io.buffer.DataBufferOutputStream.write(DataBufferOutputStream.java:55)
        org.thymeleaf.engine.ThrottledTemplateWriterOutputStreamAdapter.write(ThrottledTemplateWriterOutputStreamAdapter.java:189)
        java.base/java.nio.channels.Channels$WritableByteChannelImpl.write(Channels.java:392)
        java.base/sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:306)
        java.base/sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:381)
        java.base/sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:357)
        java.base/sun.nio.cs.StreamEncoder.lockedWrite(StreamEncoder.java:158)
        java.base/sun.nio.cs.StreamEncoder.write(StreamEncoder.java:145)
        java.base/sun.nio.cs.StreamEncoder.write(StreamEncoder.java:167)
        java.base/java.io.Writer.write(Writer.java:278)
        org.thymeleaf.engine.ThrottledTemplateWriter.write(ThrottledTemplateWriter.java:185)
        org.thymeleaf.engine.Attribute.write(Attribute.java:192)
        org.thymeleaf.engine.Attributes.write(Attributes.java:464)
        org.thymeleaf.engine.OpenElementTag.write(OpenElementTag.java:150)
        org.thymeleaf.engine.OutputTemplateHandler.handleOpenElement(OutputTemplateHandler.java:142)
        org.thymeleaf.engine.AbstractTemplateHandler.handleOpenElement(AbstractTemplateHandler.java:243)
        run.halo.app.theme.dialect.HaloPostTemplateHandler.handleOpenElement(HaloPostTemplateHandler.java:47)
        org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1576)
        org.thymeleaf.engine.OpenElementTag.beHandled(OpenElementTag.java:205)
        org.thymeleaf.engine.Model.process(Model.java:300)
        org.thymeleaf.engine.IteratedGatheringModelProcessable.processIterationModel(IteratedGatheringModelProcessable.java:368)
        org.thymeleaf.engine.IteratedGatheringModelProcessable.process(IteratedGatheringModelProcessable.java:294)
        org.thymeleaf.engine.ProcessorTemplateHandler.queueProcessable(ProcessorTemplateHandler.java:2106)
        org.thymeleaf.engine.ProcessorTemplateHandler.handleCloseElement(ProcessorTemplateHandler.java:1642)
        org.thymeleaf.engine.CloseElementTag.beHandled(CloseElementTag.java:139)
        org.thymeleaf.engine.Model.process(Model.java:300)
        org.thymeleaf.engine.StandaloneElementTagModelProcessable.process(StandaloneElementTagModelProcessable.java:114)
        org.thymeleaf.engine.ProcessorTemplateHandler.queueProcessable(ProcessorTemplateHandler.java:2106)
        org.thymeleaf.engine.ProcessorTemplateHandler.handleStandaloneElement(ProcessorTemplateHandler.java:1179)
        org.thymeleaf.engine.StandaloneElementTag.beHandled(StandaloneElementTag.java:228)
        org.thymeleaf.engine.Model.process(Model.java:300)
        org.thymeleaf.engine.OpenElementTagModelProcessable.process(OpenElementTagModelProcessable.java:110)
        org.thymeleaf.engine.ProcessorTemplateHandler.queueProcessable(ProcessorTemplateHandler.java:2106)
        org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1559)
        org.thymeleaf.engine.OpenElementTag.beHandled(OpenElementTag.java:205)
        org.thymeleaf.engine.TemplateModel.process(TemplateModel.java:155)
        org.thymeleaf.engine.ThrottledTemplateProcessor.process(ThrottledTemplateProcessor.java:235)
        org.thymeleaf.engine.ThrottledTemplateProcessor.process(ThrottledTemplateProcessor.java:200)
        org.thymeleaf.spring6.SpringWebFluxTemplateEngine$StreamThrottledTemplateProcessor.process(SpringWebFluxTemplateEngine.java:724)
        org.thymeleaf.spring6.SpringWebFluxTemplateEngine.lambda$createChunkedStream$2(SpringWebFluxTemplateEngine.java:271)
        reactor.core.publisher.FluxGenerate$GenerateSubscription.slowPath(FluxGenerate.java:271)
        reactor.core.publisher.FluxGenerate$GenerateSubscription.request(FluxGenerate.java:213)
        reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.request(FluxContextWrite.java:136)
        reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.request(FluxPeekFuseable.java:144)
        reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.requestUpstream(FluxSubscribeOn.java:131)
        reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.onSubscribe(FluxSubscribeOn.java:124)
        reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onSubscribe(FluxPeekFuseable.java:178)
        reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onSubscribe(FluxContextWrite.java:101)
        reactor.core.publisher.FluxGenerate.subscribe(FluxGenerate.java:85)
        reactor.core.publisher.InternalFluxOperator.subscribe(InternalFluxOperator.java:68)
        reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.run(FluxSubscribeOn.java:194)
        reactor.core.scheduler.BoundedElasticThreadPerTaskScheduler$SchedulerTask.run(BoundedElasticThreadPerTaskScheduler.java:1013)
        java.base/java.lang.VirtualThread.run(VirtualThread.java:329)
Fix the potential memory leak when processing template

@f2c-ci-robot f2c-ci-robot Bot added the release-note Denotes a PR that will be considered when it comes time to generate release notes. label Nov 5, 2025
@f2c-ci-robot
Copy link
Copy Markdown

f2c-ci-robot Bot commented Nov 5, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@JohnNiang JohnNiang force-pushed the bug/output-stream-may-not-be-closed branch from 1a64deb to 8825b36 Compare November 6, 2025 02:32
@JohnNiang
Copy link
Copy Markdown
Member Author

JohnNiang commented Nov 6, 2025

I'm going to merge this PR manually due to no more feedback.

@JohnNiang JohnNiang merged commit d23498e into main Nov 6, 2025
1 of 2 checks passed
@JohnNiang JohnNiang deleted the bug/output-stream-may-not-be-closed branch November 6, 2025 08:40
JohnNiang added a commit to halo-dev/halo that referenced this pull request Nov 6, 2025
f2c-ci-robot Bot pushed a commit to halo-dev/halo that referenced this pull request Nov 6, 2025
#### What type of PR is this?

/kind bug
/area core
/milestone 2.22.x

#### What this PR does / why we need it:

Supersedes <#7678>.

See halo-dev/thymeleaf#4 for more.

#### Does this PR introduce a user-facing change?

```release-note
修复潜在的内存泄漏问题
```
halo-dev-bot pushed a commit to halo-dev-bot/halo that referenced this pull request Nov 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note Denotes a PR that will be considered when it comes time to generate release notes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant