mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-19 09:16:29 +00:00
Gracefully stop a service with service stop
First send a SIGTERM to the service task and wait for it to be stopped. If it doesn’t stop in the time specified, a SIGKILL will be send to the task. Signed-off-by: stffabi <stffabi@users.noreply.github.com>
This commit is contained in:
parent
fe2ca14452
commit
7cc3fb296c
@ -7,6 +7,8 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/cio"
|
||||
@ -15,7 +17,7 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func parseCmd(ctx context.Context, command string, args []string) (*log.Entry, string, string, string, string) {
|
||||
func parseCmd(ctx context.Context, command string, args []string, cFlags ...func(*flag.FlagSet)) (*log.Entry, string, string, string, string) {
|
||||
invoked := filepath.Base(os.Args[0])
|
||||
flags := flag.NewFlagSet(command, flag.ExitOnError)
|
||||
flags.Usage = func() {
|
||||
@ -29,6 +31,10 @@ func parseCmd(ctx context.Context, command string, args []string) (*log.Entry, s
|
||||
|
||||
dumpSpec := flags.String("dump-spec", "", "Dump container spec to file before start")
|
||||
|
||||
for _, cFlag := range cFlags {
|
||||
cFlag(flags)
|
||||
}
|
||||
|
||||
if err := flags.Parse(args); err != nil {
|
||||
log.Fatal("Unable to parse args")
|
||||
}
|
||||
@ -50,10 +56,13 @@ func parseCmd(ctx context.Context, command string, args []string) (*log.Entry, s
|
||||
}
|
||||
|
||||
func stopCmd(ctx context.Context, args []string) {
|
||||
log, service, sock, path, _ := parseCmd(ctx, "stop", args)
|
||||
timeout := 10
|
||||
log, service, sock, path, _ := parseCmd(ctx, "stop", args, func(flags *flag.FlagSet) {
|
||||
flags.IntVar(&timeout, "time", 10, "Seconds to wait for stop before killing the service")
|
||||
})
|
||||
|
||||
log.Infof("Stopping service: %q", service)
|
||||
id, pid, msg, err := stop(ctx, service, sock, path)
|
||||
id, pid, msg, err := stop(ctx, service, sock, path, time.Duration(timeout)*time.Second)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal(msg)
|
||||
}
|
||||
@ -99,7 +108,7 @@ func (c *logio) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func stop(ctx context.Context, service, sock, basePath string) (string, uint32, string, error) {
|
||||
func stop(ctx context.Context, service, sock, basePath string, timeBeforeKill time.Duration) (string, uint32, string, error) {
|
||||
path := filepath.Join(basePath, service)
|
||||
|
||||
runtimeConfig := getRuntimeConfig(path)
|
||||
@ -126,16 +135,37 @@ func stop(ctx context.Context, service, sock, basePath string) (string, uint32,
|
||||
id := ctr.ID()
|
||||
pid := task.Pid()
|
||||
|
||||
err = task.Kill(ctx, 9)
|
||||
err = task.Kill(ctx, syscall.SIGTERM)
|
||||
if err != nil {
|
||||
return "", 0, "sopping task", err
|
||||
}
|
||||
|
||||
s, err := task.Wait(ctx)
|
||||
if err != nil {
|
||||
return "", 0, "waiting for task to exit", err
|
||||
}
|
||||
|
||||
select {
|
||||
case <-s:
|
||||
case <-time.After(timeBeforeKill):
|
||||
log.Infof("Task did not stop after timeout, killing it...")
|
||||
err = task.Kill(ctx, syscall.SIGKILL)
|
||||
if err != nil {
|
||||
return "", 0, "killing task", err
|
||||
}
|
||||
|
||||
_, err = task.Wait(ctx)
|
||||
s, err = task.Wait(ctx)
|
||||
if err != nil {
|
||||
return "", 0, "waiting for task to exit", err
|
||||
}
|
||||
|
||||
select {
|
||||
case <-s:
|
||||
case <-time.After(5 * time.Second):
|
||||
return "", 0, "killed, but did not stop", fmt.Errorf("Timeout waiting")
|
||||
}
|
||||
}
|
||||
|
||||
_, err = task.Delete(ctx)
|
||||
if err != nil {
|
||||
return "", 0, "deleting task", err
|
||||
|
Loading…
Reference in New Issue
Block a user