Skip to content

TemplateEngine may cause memory leak while connection interrupted #7289

Open
@JohnNiang

Description

@JohnNiang

Prerequisites

  • I have searched for related issues in the issues list.
  • This is an issue with the Halo project itself. If it is not an issue with the project itself(For example: Installation and deployment issues.), it is recommended to submit it in the Discussions.
  • I have tried disabling all plugins to rule out plugins as the cause of the problem.
  • If it is an issue with plugins and themes, please submit it in the respective plugin and theme repositories.

System information

What is the project operation method?

Docker

What happened?

TemplateEngine may cause memory leak while the connection is closed during template processing.

Related issue(s):

Reproduce Steps

  1. Execute command ab -c 100 -n 1000 -H 'Accept: text/html' -H 'Cache-Control: no-cache' http://localhost:8090/ and then press Ctrl + C to stop the thread.
  2. See logs in Halo

Relevant log output

2025-03-13T10:38:31.961+08:00 ERROR 2 --- [dedElastic-2846] org.thymeleaf.TemplateEngine             : [THYMELEAF][loomBoundedElastic-2846] Exception processing throttled template "error/error": Exception evaluating SpringEL expression: "postFinder.list(1,10)" (template: "modules/widgets/popular-posts" - line 9, col 76)

org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "postFinder.list(1,10)" (template: "modules/widgets/popular-posts" - line 9, col 76)
	at org.thymeleaf.spring6.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:292) ~[thymeleaf-spring6-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at run.halo.app.theme.ReactiveSpelVariableExpressionEvaluator.evaluate(ReactiveSpelVariableExpressionEvaluator.java:36) ~[classes/:2.20.16]
	at org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression(VariableExpression.java:166) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:66) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.standard.expression.Expression.execute(Expression.java:138) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.standard.expression.Expression.execute(Expression.java:125) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.standard.processor.StandardWithTagProcessor.doProcess(StandardWithTagProcessor.java:93) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1314) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.OpenElementTag.beHandled(OpenElementTag.java:205) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.Model.process(Model.java:300) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.StandaloneElementTagModelProcessable.process(StandaloneElementTagModelProcessable.java:114) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.ProcessorTemplateHandler.queueProcessable(ProcessorTemplateHandler.java:2106) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.ProcessorTemplateHandler.handleStandaloneElement(ProcessorTemplateHandler.java:1179) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.StandaloneElementTag.beHandled(StandaloneElementTag.java:228) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.Model.process(Model.java:300) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.IteratedGatheringModelProcessable.processIterationModel(IteratedGatheringModelProcessable.java:368) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.IteratedGatheringModelProcessable.process(IteratedGatheringModelProcessable.java:222) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.ProcessorTemplateHandler.queueProcessable(ProcessorTemplateHandler.java:2106) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.ProcessorTemplateHandler.handleCloseElement(ProcessorTemplateHandler.java:1642) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.CloseElementTag.beHandled(CloseElementTag.java:139) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.Model.process(Model.java:300) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.StandaloneElementTagModelProcessable.process(StandaloneElementTagModelProcessable.java:114) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.ProcessorTemplateHandler.queueProcessable(ProcessorTemplateHandler.java:2106) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.ProcessorTemplateHandler.handleStandaloneElement(ProcessorTemplateHandler.java:1179) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.StandaloneElementTag.beHandled(StandaloneElementTag.java:228) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.Model.process(Model.java:300) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.OpenElementTagModelProcessable.process(OpenElementTagModelProcessable.java:110) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.ProcessorTemplateHandler.handlePending(ProcessorTemplateHandler.java:2054) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.ThrottledTemplateProcessor.process(ThrottledTemplateProcessor.java:230) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.engine.ThrottledTemplateProcessor.process(ThrottledTemplateProcessor.java:200) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.spring6.SpringWebFluxTemplateEngine$StreamThrottledTemplateProcessor.process(SpringWebFluxTemplateEngine.java:720) ~[thymeleaf-spring6-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at org.thymeleaf.spring6.SpringWebFluxTemplateEngine.lambda$createChunkedStream$2(SpringWebFluxTemplateEngine.java:269) ~[thymeleaf-spring6-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	at reactor.core.publisher.FluxGenerate$GenerateSubscription.slowPath(FluxGenerate.java:271) ~[reactor-core-3.7.3.jar:3.7.3]
	at reactor.core.publisher.FluxGenerate$GenerateSubscription.request(FluxGenerate.java:213) ~[reactor-core-3.7.3.jar:3.7.3]
	at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.request(FluxPeekFuseable.java:144) ~[reactor-core-3.7.3.jar:3.7.3]
	at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.requestUpstream(FluxSubscribeOn.java:131) ~[reactor-core-3.7.3.jar:3.7.3]
	at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.onSubscribe(FluxSubscribeOn.java:124) ~[reactor-core-3.7.3.jar:3.7.3]
	at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onSubscribe(FluxPeekFuseable.java:178) ~[reactor-core-3.7.3.jar:3.7.3]
	at reactor.core.publisher.FluxGenerate.subscribe(FluxGenerate.java:85) ~[reactor-core-3.7.3.jar:3.7.3]
	at reactor.core.publisher.InternalFluxOperator.subscribe(InternalFluxOperator.java:68) ~[reactor-core-3.7.3.jar:3.7.3]
	at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.run(FluxSubscribeOn.java:194) ~[reactor-core-3.7.3.jar:3.7.3]
	at reactor.core.scheduler.BoundedElasticThreadPerTaskScheduler$SchedulerTask.run(BoundedElasticThreadPerTaskScheduler.java:1013) ~[reactor-core-3.7.3.jar:3.7.3]
	at java.base/java.lang.VirtualThread.run(Unknown Source) ~[na:na]
Caused by: reactor.core.Exceptions$ReactiveException: java.lang.InterruptedException
	at reactor.core.Exceptions$ReactiveException.fillInStackTrace(Exceptions.java:736) ~[reactor-core-3.7.3.jar:3.7.3]
	at java.base/java.lang.Throwable.<init>(Unknown Source) ~[na:na]
	at java.base/java.lang.Throwable.<init>(Unknown Source) ~[na:na]
	at java.base/java.lang.Exception.<init>(Unknown Source) ~[na:na]
	at java.base/java.lang.RuntimeException.<init>(Unknown Source) ~[na:na]
	at reactor.core.Exceptions$ReactiveException.<init>(Exceptions.java:726) ~[reactor-core-3.7.3.jar:3.7.3]
	at reactor.core.Exceptions.propagate(Exceptions.java:410) ~[reactor-core-3.7.3.jar:3.7.3]
	at reactor.core.publisher.BlockingOptionalMonoSubscriber.blockingGet(BlockingOptionalMonoSubscriber.java:158) ~[reactor-core-3.7.3.jar:3.7.3]
	at reactor.core.publisher.Mono.blockOptional(Mono.java:1861) ~[reactor-core-3.7.3.jar:3.7.3]
	at run.halo.app.infra.utils.ReactiveUtils.blockReactiveValue(ReactiveUtils.java:45) ~[classes/:na]
	at run.halo.app.infra.utils.ReactiveUtils.blockReactiveValue(ReactiveUtils.java:28) ~[classes/:na]
	at run.halo.app.theme.dialect.EvaluationContextEnhancer$ReactiveMethodExecutor.lambda$execute$1(EvaluationContextEnhancer.java:206) ~[classes/:2.20.16]
	at java.base/java.util.Optional.map(Unknown Source) ~[na:na]
	at run.halo.app.theme.dialect.EvaluationContextEnhancer$ReactiveMethodExecutor.execute(EvaluationContextEnhancer.java:206) ~[classes/:2.20.16]
	at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:152) ~[spring-expression-6.2.3.jar:6.2.3]
	at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:398) ~[spring-expression-6.2.3.jar:6.2.3]
	at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:97) ~[spring-expression-6.2.3.jar:6.2.3]
	at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:116) ~[spring-expression-6.2.3.jar:6.2.3]
	at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:338) ~[spring-expression-6.2.3.jar:6.2.3]
	at org.thymeleaf.spring6.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:265) ~[thymeleaf-spring6-3.1.3.RELEASE.jar:3.1.3.RELEASE]
	... 46 common frames omitted
	Suppressed: java.lang.Exception: #blockOptional(timeout) has been interrupted
		at reactor.core.publisher.BlockingOptionalMonoSubscriber.blockingGet(BlockingOptionalMonoSubscriber.java:160) ~[reactor-core-3.7.3.jar:3.7.3]
		... 58 common frames omitted
Caused by: java.lang.InterruptedException: null
	at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(Unknown Source) ~[na:na]
	at java.base/java.util.concurrent.CountDownLatch.await(Unknown Source) ~[na:na]
	at reactor.core.publisher.BlockingOptionalMonoSubscriber.blockingGet(BlockingOptionalMonoSubscriber.java:150) ~[reactor-core-3.7.3.jar:3.7.3]
	... 58 common frames omitted

2025-03-13T10:39:04.114+08:00 ERROR 2 --- [dedElastic-3351] 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: 
Created at:
	io.netty.buffer.PooledByteBufAllocator.newDirectBuffer(PooledByteBufAllocator.java:410)
	io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:188)
	io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:179)
	io.netty.buffer.AbstractByteBufAllocator.buffer(AbstractByteBufAllocator.java:116)
	org.springframework.core.io.buffer.NettyDataBufferFactory.allocateBuffer(NettyDataBufferFactory.java:72)
	org.springframework.core.io.buffer.NettyDataBufferFactory.allocateBuffer(NettyDataBufferFactory.java:39)
	org.thymeleaf.spring6.SpringWebFluxTemplateEngine.lambda$createChunkedStream$2(SpringWebFluxTemplateEngine.java:264)
	reactor.core.publisher.FluxGenerate$GenerateSubscription.slowPath(FluxGenerate.java:271)
	reactor.core.publisher.FluxGenerate$GenerateSubscription.request(FluxGenerate.java:213)
	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.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(Unknown Source)

Additional information

/kind bug
/area core

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/coreIssues or PRs related to the Halo Corekind/bugCategorizes issue or PR as related to a bug.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions