You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ha...@apache.org on 2026/04/21 10:30:30 UTC
(skywalking-banyandb) 01/01: Fix nil pointer panic in disk monitor during early initialization
This is an automated email from the ASF dual-hosted git repository.
hanahmily pushed a commit to branch fix/disk-monitor-nil-panic
in repository https://gitbox.apache.org/repos/asf/skywalking-banyandb.git
commit 8c7bea8a55d68fac476413498610a3e760bfa39a
Author: Hongtao Gao <ha...@gmail.com>
AuthorDate: Tue Apr 21 10:08:10 2026 +0000
Fix nil pointer panic in disk monitor during early initialization
The disk monitor's monitorLoop could panic with "invalid memory address
or nil pointer dereference" when groups are registered in the schema
repo but their schema hasn't been populated yet (race between group
creation and async schema loading).
Two fixes:
- Nil-check group.GetSchema() in findGroupWithOldestSegment before
accessing Metadata.Name to prevent the panic
- Move panic recovery from the outer loop into per-tick scope so a
recovered panic doesn't kill the monitor goroutine permanently
---
CHANGES.md | 1 +
banyand/internal/storage/disk_monitor.go | 23 +++++++++++++++--------
2 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 2136c0d02..21a3ba955 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -38,6 +38,7 @@ Release Notes.
- Fix wrong backup path of schema property.
- Fix lifecycle migration failure when the target stage has `close: true`.
- Fix stale sync request blocking watch session channel, causing repeated "channel full, skipping session" errors when a watch stream is in backoff.
+- Fix nil pointer panic in disk monitor when group schema is not yet initialized during early startup, and ensure monitor loop survives recovered panics.
### Chores
diff --git a/banyand/internal/storage/disk_monitor.go b/banyand/internal/storage/disk_monitor.go
index bcaa8550d..15205f182 100644
--- a/banyand/internal/storage/disk_monitor.go
+++ b/banyand/internal/storage/disk_monitor.go
@@ -177,22 +177,25 @@ func (dm *DiskMonitor) Stop() {
}
func (dm *DiskMonitor) monitorLoop(serviceName string) {
- defer func() {
- if r := recover(); r != nil {
- dm.logger.Error().Interface("panic", r).Msg("disk monitor panic recovered")
- }
- }()
-
for {
select {
case <-dm.stopCh:
return
case <-dm.ticker.C:
- dm.checkAndCleanup(serviceName)
+ dm.safeCheckAndCleanup(serviceName)
}
}
}
+func (dm *DiskMonitor) safeCheckAndCleanup(serviceName string) {
+ defer func() {
+ if r := recover(); r != nil {
+ dm.logger.Error().Interface("panic", r).Msg("disk monitor panic recovered")
+ }
+ }()
+ dm.checkAndCleanup(serviceName)
+}
+
func (dm *DiskMonitor) checkAndCleanup(serviceName string) {
// Check disk usage using real-time calculation for responsive forced cleanup
diskPercent, err := getRealTimeDiskUsagePercent(dm.service.GetDataPath())
@@ -344,7 +347,11 @@ func (dm *DiskMonitor) findGroupWithOldestSegment(groups []resourceSchema.Group)
// Query each group's oldest segment end time
for _, group := range groups {
- groupName := group.GetSchema().Metadata.Name
+ schema := group.GetSchema()
+ if schema == nil || schema.Metadata == nil {
+ continue
+ }
+ groupName := schema.Metadata.Name
endTime, hasSegments := dm.service.PeekOldestSegmentEndTimeInGroup(groupName)
// Only consider groups that have segments