This is an automated email from the ASF dual-hosted git repository.

hanahmily pushed a commit to branch bug/mempart-leak
in repository https://gitbox.apache.org/repos/asf/skywalking-banyandb.git

commit e387a6a1d0469ec30a366e701dc85a81756a6312
Author: Hongtao Gao <[email protected]>
AuthorDate: Tue Mar 17 12:05:25 2026 +0000

    fix(measure,stream,trace): fix memPart leak in Close and prevent 
double-release in FinishSync
    
    Transfer ownership by nil-ing s.memPart before mustAddMemPart so Close
    does not double-release on the success path; call releaseMemPart in Close
    on the error path where FinishSync was never reached.
---
 CHANGES.md                    | 1 +
 banyand/measure/write_data.go | 9 +++++++--
 banyand/stream/write_data.go  | 9 +++++++--
 banyand/trace/write_data.go   | 5 ++++-
 4 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 6c7d98d6b..55bd0b4fe 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -45,6 +45,7 @@ Release Notes.
 - Ignore take snapshot when no data.
 - Fix measure standalone write handler resetting accumulated groups on error, 
which dropped all successfully processed events in the batch.
 - Fix memory part reference leak in mustAddMemPart when tsTable loop closes.
+- Fix memory part leak in syncPartContext Close and prevent double-release in 
FinishSync.
 
 ### Document
 
diff --git a/banyand/measure/write_data.go b/banyand/measure/write_data.go
index b83ff65f6..026ad9bf7 100644
--- a/banyand/measure/write_data.go
+++ b/banyand/measure/write_data.go
@@ -43,7 +43,9 @@ func (s *syncPartContext) NewPartType(_ 
*queue.ChunkedSyncPartContext) error {
 }
 
 func (s *syncPartContext) FinishSync() error {
-       s.tsTable.mustAddMemPart(s.memPart)
+       mp := s.memPart
+       s.memPart = nil
+       s.tsTable.mustAddMemPart(mp)
        return s.Close()
 }
 
@@ -51,7 +53,10 @@ func (s *syncPartContext) Close() error {
        s.writers.MustClose()
        releaseWriters(s.writers)
        s.writers = nil
-       s.memPart = nil
+       if s.memPart != nil {
+               releaseMemPart(s.memPart)
+               s.memPart = nil
+       }
        s.tsTable = nil
        return nil
 }
diff --git a/banyand/stream/write_data.go b/banyand/stream/write_data.go
index e9bd52cc1..85876fa40 100644
--- a/banyand/stream/write_data.go
+++ b/banyand/stream/write_data.go
@@ -42,7 +42,9 @@ func (s *syncPartContext) NewPartType(_ 
*queue.ChunkedSyncPartContext) error {
 }
 
 func (s *syncPartContext) FinishSync() error {
-       s.tsTable.mustAddMemPart(s.memPart)
+       mp := s.memPart
+       s.memPart = nil
+       s.tsTable.mustAddMemPart(mp)
        return s.Close()
 }
 
@@ -50,7 +52,10 @@ func (s *syncPartContext) Close() error {
        s.writers.MustClose()
        releaseWriters(s.writers)
        s.writers = nil
-       s.memPart = nil
+       if s.memPart != nil {
+               releaseMemPart(s.memPart)
+               s.memPart = nil
+       }
        s.tsTable = nil
        return nil
 }
diff --git a/banyand/trace/write_data.go b/banyand/trace/write_data.go
index 6e44cbb7a..164035796 100644
--- a/banyand/trace/write_data.go
+++ b/banyand/trace/write_data.go
@@ -87,11 +87,13 @@ func (s *syncPartContext) FinishSync() error {
        }
 
        if s.memPart != nil {
+               mp := s.memPart
+               s.memPart = nil
                sidxPartContexts := make(map[string]*sidx.MemPart, 
len(s.sidxPartContexts))
                for _, sidxPartContext := range s.sidxPartContexts {
                        sidxPartContexts[sidxPartContext.Name()] = 
sidxPartContext.GetMemPart()
                }
-               s.tsTable.mustAddMemPart(s.memPart, sidxPartContexts)
+               s.tsTable.mustAddMemPart(mp, sidxPartContexts)
        }
        return s.Close()
 }
@@ -103,6 +105,7 @@ func (s *syncPartContext) Close() error {
                s.writers = nil
        }
        if s.memPart != nil {
+               releaseMemPart(s.memPart)
                s.memPart = nil
        }
        if s.sidxPartContexts != nil {

Reply via email to