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
+6
View File
@@ -504,6 +504,12 @@ func (a *App) DeleteServerCacheDir(serverID uuid.UUID) error {
return os.RemoveAll(path)
}
// BackgroundContext returns the application's background context
// which is canceled when the application shuts down.
func (a *App) BackgroundContext() context.Context {
return a.bgrndCtx
}
func (a *App) Shutdown() {
if a.logFile != nil {
a.logFile.Close()
+1 -1
View File
@@ -26,7 +26,7 @@ func NewRouter(app *backend.App, controller *controller.Controller, nav Navigati
App: app,
Controller: controller,
Nav: nav,
widgetPool: util.NewWidgetPool(),
widgetPool: util.NewWidgetPool(app.BackgroundContext()),
}
return r
}
+12 -2
View File
@@ -1,6 +1,7 @@
package util
import (
"context"
"sync"
"time"
@@ -33,6 +34,7 @@ const (
type WidgetPool struct {
mut sync.Mutex
pools [][]pooledWidget
cancel context.CancelFunc
}
type pooledWidget struct {
@@ -40,15 +42,23 @@ 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),
cancel: cancel,
}
go func() {
t := time.NewTicker(2 * time.Minute)
for range t.C {
defer t.Stop()
for {
select {
case <-ctx.Done():
return
case <-t.C:
p.cleanUpExpiredItems()
}
}
}()
return p
}