Procházet zdrojové kódy

chore: Fix small oncalendar channel leak

jamesread před 7 měsíci
rodič
revize
75eb1ca4a3
1 změnil soubory, kde provedl 28 přidání a 11 odebrání
  1. 28 11
      service/internal/oncalendarfile/calendar.go

+ 28 - 11
service/internal/oncalendarfile/calendar.go

@@ -2,24 +2,30 @@ package oncalendarfile
 
 import (
 	"context"
+	"os"
+	"sync"
+	"time"
+
 	"github.com/OliveTin/OliveTin/internal/acl"
 	"github.com/OliveTin/OliveTin/internal/config"
 	"github.com/OliveTin/OliveTin/internal/executor"
 	"github.com/OliveTin/OliveTin/internal/filehelper"
 	log "github.com/sirupsen/logrus"
 	"gopkg.in/yaml.v3"
-	"os"
-	"time"
-	"sync"
 )
 
+type timerEntry struct {
+	timer  *time.Timer
+	cancel context.CancelFunc
+}
+
 type ExistingTimers struct {
-	timers map[time.Time]*time.Timer
+	timers map[time.Time]timerEntry
 }
 
 var (
-	scheduleMap map[string]ExistingTimers = make(map[string]ExistingTimers, 0)
-	scheduleMapMutex sync.Mutex = sync.Mutex{}
+	scheduleMap      = make(map[string]ExistingTimers)
+	scheduleMapMutex sync.RWMutex
 )
 
 func Schedule(cfg *config.Config, ex *executor.Executor) {
@@ -41,18 +47,19 @@ func clearExistingTimers(action *config.Action) {
 	defer scheduleMapMutex.Unlock()
 
 	if _, exists := scheduleMap[action.ID]; exists {
-		for instant, timer := range scheduleMap[action.ID].timers {
+		for instant, entry := range scheduleMap[action.ID].timers {
 			log.WithFields(log.Fields{
 				"instant":     instant,
 				"actionTitle": action.Title,
 			}).Infof("Clearing existing scheduled action from calendar")
 
-			timer.Stop()
+			entry.cancel()
+			entry.timer.Stop()
 		}
 	}
 
 	scheduleMap[action.ID] = ExistingTimers{
-		timers: make(map[time.Time]*time.Timer),
+		timers: make(map[time.Time]timerEntry),
 	}
 }
 
@@ -113,19 +120,29 @@ func sleepUntil(ctx context.Context, instant time.Time, action *config.Action, c
 		"actionTitle": action.Title,
 	}).Infof("Scheduling action on calendar")
 
+	childCtx, cancel := context.WithCancel(ctx)
 	timer := time.NewTimer(time.Until(instant))
 
 	scheduleMapMutex.Lock()
-	scheduleMap[action.ID].timers[instant] = timer
+	if _, exists := scheduleMap[action.ID]; !exists {
+		scheduleMap[action.ID] = ExistingTimers{
+			timers: make(map[time.Time]timerEntry),
+		}
+	}
+	scheduleMap[action.ID].timers[instant] = timerEntry{
+		timer:  timer,
+		cancel: cancel,
+	}
 	scheduleMapMutex.Unlock()
 
 	defer timer.Stop()
+	defer cancel()
 
 	select {
 	case <-timer.C:
 		exec(instant, action, cfg, ex)
 		return
-	case <-ctx.Done():
+	case <-childCtx.Done():
 		log.Infof("Cancelled scheduled action")
 		return
 	}