2018-10-08 19:20:28 +00:00
|
|
|
package tunnel
|
2018-05-01 23:45:06 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
"os/signal"
|
|
|
|
"syscall"
|
|
|
|
"time"
|
2020-04-29 20:51:32 +00:00
|
|
|
|
2020-11-25 06:55:13 +00:00
|
|
|
"github.com/rs/zerolog"
|
2018-05-01 23:45:06 +00:00
|
|
|
)
|
|
|
|
|
2020-12-28 18:10:01 +00:00
|
|
|
const LogFieldSignal = "signal"
|
|
|
|
|
2018-05-01 23:45:06 +00:00
|
|
|
// waitForSignal notifies all routines to shutdownC immediately by closing the
|
|
|
|
// shutdownC when one of the routines in main exits, or when this process receives
|
|
|
|
// SIGTERM/SIGINT
|
2020-11-25 06:55:13 +00:00
|
|
|
func waitForSignal(errC chan error, shutdownC chan struct{}, log *zerolog.Logger) error {
|
2018-05-01 23:45:06 +00:00
|
|
|
signals := make(chan os.Signal, 10)
|
|
|
|
signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT)
|
|
|
|
defer signal.Stop(signals)
|
|
|
|
|
|
|
|
select {
|
|
|
|
case err := <-errC:
|
2020-12-28 18:10:01 +00:00
|
|
|
log.Err(err).Msg("terminating due to error")
|
2018-05-01 23:45:06 +00:00
|
|
|
close(shutdownC)
|
|
|
|
return err
|
2020-04-28 00:55:27 +00:00
|
|
|
case s := <-signals:
|
2020-12-28 18:10:01 +00:00
|
|
|
log.Info().Str(LogFieldSignal, s.String()).Msg("terminating due to signal")
|
2018-05-01 23:45:06 +00:00
|
|
|
close(shutdownC)
|
|
|
|
case <-shutdownC:
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// waitForSignalWithGraceShutdown notifies all routines to shutdown immediately
|
|
|
|
// by closing the shutdownC when one of the routines in main exits.
|
|
|
|
// When this process recieves SIGTERM/SIGINT, it closes the graceShutdownC to
|
|
|
|
// notify certain routines to start graceful shutdown. When grace period is over,
|
|
|
|
// or when some routine exits, it notifies the rest of the routines to shutdown
|
|
|
|
// immediately by closing shutdownC.
|
|
|
|
// In the case of handling commands from Windows Service Manager, closing graceShutdownC
|
|
|
|
// initiate graceful shutdown.
|
|
|
|
func waitForSignalWithGraceShutdown(errC chan error,
|
|
|
|
shutdownC, graceShutdownC chan struct{},
|
|
|
|
gracePeriod time.Duration,
|
2020-11-25 06:55:13 +00:00
|
|
|
logger *zerolog.Logger,
|
2018-05-01 23:45:06 +00:00
|
|
|
) error {
|
|
|
|
signals := make(chan os.Signal, 10)
|
|
|
|
signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT)
|
|
|
|
defer signal.Stop(signals)
|
|
|
|
|
|
|
|
select {
|
|
|
|
case err := <-errC:
|
2020-11-25 06:55:13 +00:00
|
|
|
logger.Info().Msgf("Initiating graceful shutdown due to %v ...", err)
|
2018-05-01 23:45:06 +00:00
|
|
|
close(graceShutdownC)
|
|
|
|
close(shutdownC)
|
|
|
|
return err
|
2020-04-28 00:55:27 +00:00
|
|
|
case s := <-signals:
|
2020-11-25 06:55:13 +00:00
|
|
|
logger.Info().Msgf("Initiating graceful shutdown due to signal %s ...", s)
|
2018-05-01 23:45:06 +00:00
|
|
|
close(graceShutdownC)
|
2020-11-25 06:55:13 +00:00
|
|
|
waitForGracePeriod(signals, errC, shutdownC, gracePeriod)
|
2018-05-01 23:45:06 +00:00
|
|
|
case <-graceShutdownC:
|
2020-11-25 06:55:13 +00:00
|
|
|
waitForGracePeriod(signals, errC, shutdownC, gracePeriod)
|
2018-05-01 23:45:06 +00:00
|
|
|
case <-shutdownC:
|
|
|
|
close(graceShutdownC)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func waitForGracePeriod(signals chan os.Signal,
|
|
|
|
errC chan error,
|
|
|
|
shutdownC chan struct{},
|
|
|
|
gracePeriod time.Duration,
|
|
|
|
) {
|
|
|
|
// Unregister signal handler early, so the client can send a second SIGTERM/SIGINT
|
|
|
|
// to force shutdown cloudflared
|
|
|
|
signal.Stop(signals)
|
|
|
|
graceTimerTick := time.Tick(gracePeriod)
|
|
|
|
// send close signal via shutdownC when grace period expires or when an
|
|
|
|
// error is encountered.
|
|
|
|
select {
|
|
|
|
case <-graceTimerTick:
|
|
|
|
case <-errC:
|
|
|
|
}
|
|
|
|
close(shutdownC)
|
|
|
|
}
|