Skip to content

Commit

Permalink
Add code to trigger module reinitialization on SIGUSR2
Browse files Browse the repository at this point in the history
  • Loading branch information
foxcpp committed Jan 29, 2025
1 parent 503c9f8 commit 3ce6ebf
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 7 deletions.
40 changes: 39 additions & 1 deletion maddy.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,12 @@ func moduleStop(c *container.C) {
func moduleMain(configPath string) error {
log.DefaultLogger.Msg("loading configuration...")

// Make path absolute to make sure we can still read it if current directory changes (in moduleConfigure).
configPath, err := filepath.Abs(configPath)
if err != nil {
return err
}

c, err := moduleConfigure(configPath)
if err != nil {
return err
Expand All @@ -389,7 +395,12 @@ func moduleMain(configPath string) error {
c.DefaultLogger.Msg("server started", "version", Version)

systemdStatus(SDReady, "Listening for incoming connections...")
handleSignals()
for handleSignals() {
systemdStatus(SDReloading, "Reloading state...")
hooks.RunHooks(hooks.EventReload)

c = moduleReload(c, configPath)
}

c.DefaultLogger.Msg("server stopping...")
systemdStatus(SDStopping, "Waiting for running transactions to complete...")
Expand All @@ -399,6 +410,33 @@ func moduleMain(configPath string) error {
return nil
}

func moduleReload(oldContainer *container.C, configPath string) *container.C {
oldContainer.DefaultLogger.Msg("reloading server...")

oldContainer.DefaultLogger.Msg("loading new configuration...")
newContainer, err := moduleConfigure(configPath)
if err != nil {
oldContainer.DefaultLogger.Error("failed to load new configuration", err)
return oldContainer
}

oldContainer.DefaultLogger.Msg("configuration loaded")

oldContainer.DefaultLogger.Msg("starting new server")
if err := moduleStart(newContainer); err != nil {
oldContainer.DefaultLogger.Error("failed to start new server", err)
container.Global = oldContainer
return oldContainer
}

newContainer.DefaultLogger.Msg("server started", "version", Version)
oldContainer.DefaultLogger.Msg("stopping server")
moduleStop(oldContainer)
oldContainer.DefaultLogger.Msg("server stopped")

return newContainer
}

func RegisterModules(c *container.C, globals map[string]interface{}, nodes []config.Node) (err error) {
var endpoints []struct {
Endpoint module.LifetimeModule
Expand Down
11 changes: 5 additions & 6 deletions signal.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ import (
// (SIGTERM, SIGHUP, SIGINT) will cause this function to return.
//
// SIGUSR1 will call reinitLogging without returning.
func handleSignals() os.Signal {
func handleSignals() (reload bool) {
sig := make(chan os.Signal, 5)
signal.Notify(sig, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGINT, syscall.SIGUSR1, syscall.SIGUSR2)
defer signal.Stop(sig)

for {
switch s := <-sig; s {
Expand All @@ -48,10 +49,8 @@ func handleSignals() os.Signal {
hooks.RunHooks(hooks.EventLogRotate)
systemdStatus(SDReady, "Listening for incoming connections...")
case syscall.SIGUSR2:
log.Printf("signal received (%s), reloading state", s.String())
systemdStatus(SDReloading, "Reloading state...")
hooks.RunHooks(hooks.EventReload)
systemdStatus(SDReady, "Listening for incoming connections...")
log.Printf("signal received (%s), reloading configuration", s.String())
return true
default:
go func() {
s := handleSignals()
Expand All @@ -60,7 +59,7 @@ func handleSignals() os.Signal {
}()

log.Printf("signal received (%v), next signal will force immediate shutdown.", s)
return s
return false
}
}
}

0 comments on commit 3ce6ebf

Please sign in to comment.