From e19e904179caf7f2f97fd13b162fe6b8db75d739 Mon Sep 17 00:00:00 2001 From: anime Date: Sat, 11 Oct 2025 00:34:15 +0800 Subject: [PATCH 1/3] fix(channel): handle dynamic frequency updates - replace infinite sleep loop with time.Ticker to avoid goroutine leaks - add immediate initial test execution before ticker starts - implement frequency change detection and ticker recreation - ensure proper ticker cleanup when loop exits or feature disabled --- controller/channel-test.go | 51 ++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/controller/channel-test.go b/controller/channel-test.go index 4778ff0c7..55b187ebb 100644 --- a/controller/channel-test.go +++ b/controller/channel-test.go @@ -617,22 +617,47 @@ var autoTestChannelsOnce sync.Once func AutomaticallyTestChannels() { autoTestChannelsOnce.Do(func() { - for { - if !operation_setting.GetMonitorSetting().AutoTestChannelEnabled { - time.Sleep(10 * time.Minute) - continue - } - frequency := operation_setting.GetMonitorSetting().AutoTestChannelMinutes - common.SysLog(fmt.Sprintf("automatically test channels with interval %d minutes", frequency)) + go func() { for { - time.Sleep(time.Duration(frequency) * time.Minute) - common.SysLog("automatically testing all channels") - _ = testAllChannels(false) - common.SysLog("automatically channel test finished") if !operation_setting.GetMonitorSetting().AutoTestChannelEnabled { - break + time.Sleep(10 * time.Minute) + continue } + + frequency := operation_setting.GetMonitorSetting().AutoTestChannelMinutes + common.SysLog(fmt.Sprintf("starting tests with interval %d minutes", frequency)) + ticker := time.NewTicker(time.Duration(frequency) * time.Minute) + + // 使用匿名函数来绑定 ticker 的生命周期 + func() { + defer ticker.Stop() + + // 立即执行一次 + common.SysLog("automatically testing all channels (initial run)") + _ = testAllChannels(false) + common.SysLog("automatically channel test finished") + + // 开始循环等待后续的 tick + for { + select { + case <-ticker.C: + // 检查是否需要退出或重新配置 + if !operation_setting.GetMonitorSetting().AutoTestChannelEnabled { + return + } + newFrequency := operation_setting.GetMonitorSetting().AutoTestChannelMinutes + if newFrequency != frequency { + return + } + + // 执行定时任务 + common.SysLog("automatically testing all channels") + _ = testAllChannels(false) + common.SysLog("automatically channel test finished") + } + } + }() } - } + }() }) } From 7351480365b303319c36120efc03ceb962915b64 Mon Sep 17 00:00:00 2001 From: anime Date: Sat, 11 Oct 2025 00:53:26 +0800 Subject: [PATCH 2/3] fix(channel): handle dynamic frequency updates --- controller/channel-test.go | 57 +++++++++++--------------------------- 1 file changed, 16 insertions(+), 41 deletions(-) diff --git a/controller/channel-test.go b/controller/channel-test.go index 55b187ebb..b6ed1a043 100644 --- a/controller/channel-test.go +++ b/controller/channel-test.go @@ -617,47 +617,22 @@ var autoTestChannelsOnce sync.Once func AutomaticallyTestChannels() { autoTestChannelsOnce.Do(func() { - go func() { - for { - if !operation_setting.GetMonitorSetting().AutoTestChannelEnabled { - time.Sleep(10 * time.Minute) - continue - } - - frequency := operation_setting.GetMonitorSetting().AutoTestChannelMinutes - common.SysLog(fmt.Sprintf("starting tests with interval %d minutes", frequency)) - ticker := time.NewTicker(time.Duration(frequency) * time.Minute) - - // 使用匿名函数来绑定 ticker 的生命周期 - func() { - defer ticker.Stop() - - // 立即执行一次 - common.SysLog("automatically testing all channels (initial run)") - _ = testAllChannels(false) - common.SysLog("automatically channel test finished") - - // 开始循环等待后续的 tick - for { - select { - case <-ticker.C: - // 检查是否需要退出或重新配置 - if !operation_setting.GetMonitorSetting().AutoTestChannelEnabled { - return - } - newFrequency := operation_setting.GetMonitorSetting().AutoTestChannelMinutes - if newFrequency != frequency { - return - } - - // 执行定时任务 - common.SysLog("automatically testing all channels") - _ = testAllChannels(false) - common.SysLog("automatically channel test finished") - } - } - }() + for { + if !operation_setting.GetMonitorSetting().AutoTestChannelEnabled { + time.Sleep(10 * time.Minute) + continue } - }() + for { + frequency := operation_setting.GetMonitorSetting().AutoTestChannelMinutes + common.SysLog(fmt.Sprintf("automatically test channels with interval %d minutes", frequency)) + time.Sleep(time.Duration(frequency) * time.Minute) + common.SysLog("automatically testing all channels") + _ = testAllChannels(false) + common.SysLog("automatically channel test finished") + if !operation_setting.GetMonitorSetting().AutoTestChannelEnabled { + break + } + } + } }) } From 57e5d67f86a494e49f5eb43fb6113147687638d2 Mon Sep 17 00:00:00 2001 From: anime Date: Sat, 11 Oct 2025 00:59:13 +0800 Subject: [PATCH 3/3] fix(channel): move log statement after sleep in auto-test loop --- controller/channel-test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/channel-test.go b/controller/channel-test.go index b6ed1a043..5bbc20ebc 100644 --- a/controller/channel-test.go +++ b/controller/channel-test.go @@ -624,8 +624,8 @@ func AutomaticallyTestChannels() { } for { frequency := operation_setting.GetMonitorSetting().AutoTestChannelMinutes - common.SysLog(fmt.Sprintf("automatically test channels with interval %d minutes", frequency)) time.Sleep(time.Duration(frequency) * time.Minute) + common.SysLog(fmt.Sprintf("automatically test channels with interval %d minutes", frequency)) common.SysLog("automatically testing all channels") _ = testAllChannels(false) common.SysLog("automatically channel test finished")