Bug Description
Three background goroutines use infinite loops (for range ticker.C or for {}) with no stop mechanism. Once spawned, they can never be terminated. The defer ticker.Stop() calls are dead code because the goroutines never exit.
How to Reproduce
Steps to reproduce the behavior:
- Create a Fiber app with logger middleware (containing
${time}) and cache middleware
- Run
go test -count=5 ./... or use goleak to detect leaked goroutines
- Observe leaked goroutine count increases with each middleware instantiation
- In tests that create/teardown Fiber apps, goroutines accumulate indefinitely
Affected Goroutines
1. Logger timestamp updater β middleware/logger/logger.go:43-48
go func() {
for {
time.Sleep(cfg.TimeInterval)
timestamp.Store(time.Now().In(cfg.timeZoneLocation).Format(cfg.TimeFormat))
}
}()
No context, no done channel, no way to stop.
2. Cache timestamp updater β middleware/cache/cache.go:173-179
go func() {
ticker := time.NewTicker(timestampUpdatePeriod)
defer ticker.Stop() // dead code β goroutine never exits
for range ticker.C {
atomic.StoreUint64(×tamp, safeUnixSeconds(time.Now()))
}
}()
3. internal/memory GC β internal/memory/memory.go:110-141
func (s *Storage) gc(sleep time.Duration) {
ticker := time.NewTicker(sleep)
defer ticker.Stop() // dead code β goroutine never exits
for range ticker.C {
// ... cleanup expired entries ...
}
}
Storage has no Close() method and no done channel.
Expected Behavior
All three should follow the pattern already used in internal/storage/memory/memory.go:
func (s *Storage) gc() {
ticker := time.NewTicker(s.gcInterval)
defer ticker.Stop()
for {
select {
case <-s.done: // β proper shutdown signal
return
case <-ticker.C:
// ...
}
}
}
Each needs a done chan struct{} field and a Close() or Stop() method. The middleware constructors should expose cleanup or accept a context.
Fiber Version
v3 (latest main branch)
Bug Description
Three background goroutines use infinite loops (
for range ticker.Corfor {}) with no stop mechanism. Once spawned, they can never be terminated. Thedefer ticker.Stop()calls are dead code because the goroutines never exit.How to Reproduce
Steps to reproduce the behavior:
${time}) and cache middlewarego test -count=5 ./...or usegoleakto detect leaked goroutinesAffected Goroutines
1. Logger timestamp updater β
middleware/logger/logger.go:43-48No context, no done channel, no way to stop.
2. Cache timestamp updater β
middleware/cache/cache.go:173-1793. internal/memory GC β
internal/memory/memory.go:110-141Storagehas noClose()method and nodonechannel.Expected Behavior
All three should follow the pattern already used in
internal/storage/memory/memory.go:Each needs a
done chan struct{}field and aClose()orStop()method. The middleware constructors should expose cleanup or accept a context.Fiber Version
v3 (latest main branch)