MCPcopy
hub / github.com/caddyserver/caddy / Stop

Method Stop

modules/caddyhttp/app.go:655–801  ·  view source on GitHub ↗

Stop gracefully shuts down the HTTP server.

()

Source from the content-addressed store, hash-verified

653
654// Stop gracefully shuts down the HTTP server.
655func (app *App) Stop() error {
656 ctx := context.Background()
657
658 // see if any listeners in our config will be closing or if they are continuing
659 // through a reload; because if any are closing, we will enforce shutdown delay
660 var delay bool
661 scheduledTime := time.Now().Add(time.Duration(app.ShutdownDelay))
662 if app.ShutdownDelay > 0 {
663 for _, server := range app.Servers {
664 for _, na := range server.addresses {
665 for _, addr := range na.Expand() {
666 if caddy.ListenerUsage(addr.Network, addr.JoinHostPort(0)) < 2 {
667 app.logger.Debug("listener closing and shutdown delay is configured", zap.String("address", addr.String()))
668 server.shutdownAt.Store(&scheduledTime)
669 delay = true
670 } else {
671 app.logger.Debug("shutdown delay configured but listener will remain open", zap.String("address", addr.String()))
672 }
673 }
674 }
675 }
676 }
677
678 // honor scheduled/delayed shutdown time
679 if delay {
680 app.logger.Info("shutdown scheduled",
681 zap.Duration("delay_duration", time.Duration(app.ShutdownDelay)),
682 zap.Time("time", scheduledTime))
683 time.Sleep(time.Duration(app.ShutdownDelay))
684 }
685
686 // enforce grace period if configured
687 if app.GracePeriod > 0 {
688 var cancel context.CancelFunc
689 timeout := time.Duration(app.GracePeriod)
690 ctx, cancel = context.WithTimeoutCause(ctx, timeout, fmt.Errorf("server graceful shutdown %ds timeout", int(timeout.Seconds())))
691 defer cancel()
692 app.logger.Info("servers shutting down; grace period initiated", zap.Duration("duration", timeout))
693 } else {
694 app.logger.Info("servers shutting down with eternal grace period")
695 }
696
697 // goroutines aren't guaranteed to be scheduled right away,
698 // so we'll use one WaitGroup to wait for all the goroutines
699 // to start their server shutdowns, and another to wait for
700 // them to finish; we'll always block for them to start so
701 // that when we return the caller can be confident* that the
702 // old servers are no longer accepting new connections
703 // (* the scheduler might still pause them right before
704 // calling Shutdown(), but it's unlikely)
705 var startedShutdown, finishedShutdown sync.WaitGroup
706
707 // these will run in goroutines
708 stopServer := func(server *Server) {
709 defer finishedShutdown.Done()
710 startedShutdown.Done()
711
712 // possible if server failed to Start

Callers 1

CleanupMethod · 0.95

Implementers 6

fooModuleadmin_test.go
PKImodules/caddypki/pki.go
TLSmodules/caddytls/tls.go
Filesystemsmodules/caddyfs/filesystem.go
Appmodules/caddyhttp/app.go
Appmodules/caddyevents/app.go

Calls 8

DurationMethod · 0.80
ExpandMethod · 0.80
JoinHostPortMethod · 0.80
shutdownMethod · 0.80
AddMethod · 0.45
StringMethod · 0.45
ErrorMethod · 0.45
CloseMethod · 0.45

Tested by

no test coverage detected