fix: Prevent goroutine leak in Crontab by adding graceful shutdown support#3292
fix: Prevent goroutine leak in Crontab by adding graceful shutdown support#3292tharunn0 wants to merge 3 commits intogofr-dev:developmentfrom
Conversation
There was a problem hiding this comment.
@tharunn0 Thanks for the effort to make GoFr better. Here are a few things that should be fixed before we go ahead with the PR:
Issue 1 : Double-Stop panics
close(c.done) will panic if Stop() is called twice. While ticker.Stop() is idempotent, close() on an already-closed channel is not. Use sync.Once:
type Crontab struct {
// ...
done chan struct{}
stopOnce sync.Once
}
func (c *Crontab) Stop() {
c.stopOnce.Do(func() {
c.ticker.Stop()
close(c.done)
})
}Issue 2 Shutdown ordering
cron.Stop() is placed after a.container.Close() in Shutdown(). This means datasources are closed before cron scheduling stops — a cron job could fire against closed datasources in that window. Move cron stop before container close:
if a.cron != nil {
a.cron.Stop()
}
if a.container != nil {
err = errors.Join(err, a.container.Close())
}Issue 3 : Missing integration test
TestCrontab_Stop only tests standalone Stop(). Consider adding a test that verifies App.Shutdown() properly stops cron — e.g., create an App, add a cron job, call Shutdown, assert the goroutine exits.
…cation shutdown sequence
Description:
Updates the crontab background job runner to support graceful shutdown, replacing the infinite
for ... rangeticker loop with aselectstatement that listens for a termination signal.Previously, terminating the application would inadvertently leak the associated background goroutine because it lacked an explicit exit condition.
The changes align the crontab implementation with the framework's graceful shutdown lifecycle by integrating the new
Crontab.Stop()method intoApp.Shutdown.Fixes goroutine leak during crontab shutdown
Breaking Changes (if applicable):
Additional Information:
Checklist:
Fixes #3211