From 3ffb6a61130298cd27636df2b64a53e2161cdced Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Wed, 19 Jan 2022 00:23:52 +0000 Subject: [PATCH] shimv2: handle sigint/sigterm This causes sigint/sigterm to trigger a shutdown of the shim. It is needed because otherwise the v2 shim hangs system shutdown. Signed-off-by: Brian Goff --- runtime/v2/shim/shim.go | 10 ++++++---- runtime/v2/shim/shim_unix.go | 20 +++++++++++++++++++- runtime/v2/shim/shim_windows.go | 5 ++++- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/runtime/v2/shim/shim.go b/runtime/v2/shim/shim.go index 289b489d648..59e522cede4 100644 --- a/runtime/v2/shim/shim.go +++ b/runtime/v2/shim/shim.go @@ -305,7 +305,7 @@ func run(ctx context.Context, manager Manager, initFunc Init, name string, confi "pid": os.Getpid(), "namespace": namespaceFlag, }) - go handleSignals(ctx, logger, signals) + go reap(ctx, logger, signals) ss, err := manager.Stop(ctx, id) if err != nil { return err @@ -428,7 +428,7 @@ func run(ctx context.Context, manager Manager, initFunc Init, name string, confi } } - if err := serve(ctx, server, signals); err != nil { + if err := serve(ctx, server, signals, sd.Shutdown); err != nil { if err != shutdown.ErrShutdown { return err } @@ -450,7 +450,7 @@ func run(ctx context.Context, manager Manager, initFunc Init, name string, confi // serve serves the ttrpc API over a unix socket in the current working directory // and blocks until the context is canceled -func serve(ctx context.Context, server *ttrpc.Server, signals chan os.Signal) error { +func serve(ctx context.Context, server *ttrpc.Server, signals chan os.Signal, shutdown func()) error { dump := make(chan os.Signal, 32) setupDumpStacks(dump) @@ -480,7 +480,9 @@ func serve(ctx context.Context, server *ttrpc.Server, signals chan os.Signal) er dumpStacks(logger) } }() - return handleSignals(ctx, logger, signals) + + go handleExitSignals(ctx, logger, shutdown) + return reap(ctx, logger, signals) } func dumpStacks(logger *logrus.Entry) { diff --git a/runtime/v2/shim/shim_unix.go b/runtime/v2/shim/shim_unix.go index 0701fdc6f64..e2dab0931ea 100644 --- a/runtime/v2/shim/shim_unix.go +++ b/runtime/v2/shim/shim_unix.go @@ -71,7 +71,7 @@ func serveListener(path string) (net.Listener, error) { return l, nil } -func handleSignals(ctx context.Context, logger *logrus.Entry, signals chan os.Signal) error { +func reap(ctx context.Context, logger *logrus.Entry, signals chan os.Signal) error { logger.Info("starting signal loop") for { @@ -79,6 +79,8 @@ func handleSignals(ctx context.Context, logger *logrus.Entry, signals chan os.Si case <-ctx.Done(): return ctx.Err() case s := <-signals: + // Exit signals are handled separately from this loop + // They get registered with this channel so that we can ignore such signals for short-running actions (e.g. `delete`) switch s { case unix.SIGCHLD: if err := reaper.Reap(); err != nil { @@ -90,6 +92,22 @@ func handleSignals(ctx context.Context, logger *logrus.Entry, signals chan os.Si } } +func handleExitSignals(ctx context.Context, logger *logrus.Entry, cancel context.CancelFunc) { + ch := make(chan os.Signal, 32) + signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) + + for { + select { + case s := <-ch: + logger.WithField("signal", s).Debugf("Caught exit signal") + cancel() + return + case <-ctx.Done(): + return + } + } +} + func openLog(ctx context.Context, _ string) (io.Writer, error) { return fifo.OpenFifoDup2(ctx, "log", unix.O_WRONLY, 0700, int(os.Stderr.Fd())) } diff --git a/runtime/v2/shim/shim_windows.go b/runtime/v2/shim/shim_windows.go index 4eef8c9ffec..4b098ab1630 100644 --- a/runtime/v2/shim/shim_windows.go +++ b/runtime/v2/shim/shim_windows.go @@ -46,10 +46,13 @@ func serveListener(path string) (net.Listener, error) { return nil, errors.New("not supported") } -func handleSignals(ctx context.Context, logger *logrus.Entry, signals chan os.Signal) error { +func reap(ctx context.Context, logger *logrus.Entry, signals chan os.Signal) error { return errors.New("not supported") } +func handleExitSignals(ctx context.Context, logger *logrus.Entry, cancel context.CancelFunc) { +} + func openLog(ctx context.Context, _ string) (io.Writer, error) { return nil, errors.New("not supported") }