Enhance timeout handling in InstanceManager with goroutine recovery and shutdown support

This commit is contained in:
2025-08-17 22:49:28 +02:00
parent d70bb634cd
commit 78eda77e44
2 changed files with 235 additions and 629 deletions

View File

@@ -35,16 +35,21 @@ type instanceManager struct {
// Timeout checker // Timeout checker
timeoutChecker *time.Ticker timeoutChecker *time.Ticker
shutdownChan chan struct{}
} }
// NewInstanceManager creates a new instance of InstanceManager. // NewInstanceManager creates a new instance of InstanceManager.
func NewInstanceManager(instancesConfig config.InstancesConfig) InstanceManager { func NewInstanceManager(instancesConfig config.InstancesConfig) InstanceManager {
if instancesConfig.TimeoutCheckInterval <= 0 {
instancesConfig.TimeoutCheckInterval = 5 // Default to 5 minutes if not set
}
im := &instanceManager{ im := &instanceManager{
instances: make(map[string]*instance.Process), instances: make(map[string]*instance.Process),
ports: make(map[int]bool), ports: make(map[int]bool),
instancesConfig: instancesConfig, instancesConfig: instancesConfig,
timeoutChecker: time.NewTicker(time.Duration(instancesConfig.TimeoutCheckInterval) * time.Minute), timeoutChecker: time.NewTicker(time.Duration(instancesConfig.TimeoutCheckInterval) * time.Minute),
shutdownChan: make(chan struct{}),
} }
// Load existing instances from disk // Load existing instances from disk
@@ -52,10 +57,25 @@ func NewInstanceManager(instancesConfig config.InstancesConfig) InstanceManager
log.Printf("Error loading instances: %v", err) log.Printf("Error loading instances: %v", err)
} }
// Start the timeout checker goroutine after initialization is complete
go func() { go func() {
for range im.timeoutChecker.C { defer func() {
if r := recover(); r != nil {
log.Printf("Timeout checker goroutine recovered from panic: %v", r)
}
}()
for {
select {
case <-im.timeoutChecker.C:
// Check if manager is still valid before proceeding
if im != nil {
im.checkAllTimeouts() im.checkAllTimeouts()
} }
case <-im.shutdownChan:
return // Exit goroutine on shutdown
}
}
}() }()
return im return im
@@ -113,6 +133,14 @@ func (im *instanceManager) Shutdown() {
im.timeoutChecker = nil im.timeoutChecker = nil
} }
// Signal the shutdown channel to exit the goroutine
select {
case <-im.shutdownChan:
// Channel already closed
default:
close(im.shutdownChan)
}
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(len(im.instances)) wg.Add(len(im.instances))

File diff suppressed because it is too large Load Diff