Fix WidgetPool goroutine and ticker leak

- Add context cancellation to WidgetPool cleanup goroutine
- Properly stop ticker when context is canceled
- Add BackgroundContext() getter method to App for context access
- Pass application context to NewWidgetPool for lifecycle management

This fixes a resource leak where the cleanup goroutine would run
indefinitely without any way to stop it, preventing proper cleanup
on application shutdown.
This commit is contained in:
Gianluca Boiano
2026-02-02 16:31:56 +01:00
parent 43e8d0a453
commit ada1564be7
3 changed files with 23 additions and 7 deletions
+16 -6
View File
@@ -1,6 +1,7 @@
package util
import (
"context"
"sync"
"time"
@@ -31,8 +32,9 @@ const (
// A pool to share commonly-used widgets across pages to reduce
// creation of new widgets and memory allocations.
type WidgetPool struct {
mut sync.Mutex
pools [][]pooledWidget
mut sync.Mutex
pools [][]pooledWidget
cancel context.CancelFunc
}
type pooledWidget struct {
@@ -40,14 +42,22 @@ type pooledWidget struct {
releasedAt int64 // unixMillis
}
func NewWidgetPool() *WidgetPool {
func NewWidgetPool(ctx context.Context) *WidgetPool {
ctx, cancel := context.WithCancel(ctx)
p := &WidgetPool{
pools: make([][]pooledWidget, numWidgetTypes),
pools: make([][]pooledWidget, numWidgetTypes),
cancel: cancel,
}
go func() {
t := time.NewTicker(2 * time.Minute)
for range t.C {
p.cleanUpExpiredItems()
defer t.Stop()
for {
select {
case <-ctx.Done():
return
case <-t.C:
p.cleanUpExpiredItems()
}
}
}()
return p