mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
e918d02139
This removes libcontainer's own error wrapping system, consisting of a few types and functions, aimed at typization, wrapping and unwrapping of errors, as well as saving error stack traces. Since Go 1.13 now provides its own error wrapping mechanism and a few related functions, it makes sense to switch to it. While doing that, improve some error messages so that they start with "error", "unable to", or "can't". A few things that are worth mentioning: 1. We lose stack traces (which were never shown anyway). 2. Users of libcontainer that relied on particular errors (like ContainerNotExists) need to switch to using errors.Is with the new errors defined in error.go. 3. encoding/json is unable to unmarshal the built-in error type, so we have to introduce initError and wrap the errors into it (basically passing the error as a string). This is the same as it was before, just a tad simpler (actually the initError is a type that got removed in commit afa844311; also suddenly ierr variable name makes sense now). Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
90 lines
2.2 KiB
Go
90 lines
2.2 KiB
Go
// +build !solaris
|
|
|
|
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/opencontainers/runc/libcontainer"
|
|
"github.com/urfave/cli"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
func killContainer(container libcontainer.Container) error {
|
|
_ = container.Signal(unix.SIGKILL, false)
|
|
for i := 0; i < 100; i++ {
|
|
time.Sleep(100 * time.Millisecond)
|
|
if err := container.Signal(unix.Signal(0), false); err != nil {
|
|
destroy(container)
|
|
return nil
|
|
}
|
|
}
|
|
return errors.New("container init still running")
|
|
}
|
|
|
|
var deleteCommand = cli.Command{
|
|
Name: "delete",
|
|
Usage: "delete any resources held by the container often used with detached container",
|
|
ArgsUsage: `<container-id>
|
|
|
|
Where "<container-id>" is the name for the instance of the container.
|
|
|
|
EXAMPLE:
|
|
For example, if the container id is "ubuntu01" and runc list currently shows the
|
|
status of "ubuntu01" as "stopped" the following will delete resources held for
|
|
"ubuntu01" removing "ubuntu01" from the runc list of containers:
|
|
|
|
# runc delete ubuntu01`,
|
|
Flags: []cli.Flag{
|
|
cli.BoolFlag{
|
|
Name: "force, f",
|
|
Usage: "Forcibly deletes the container if it is still running (uses SIGKILL)",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
if err := checkArgs(context, 1, exactArgs); err != nil {
|
|
return err
|
|
}
|
|
|
|
id := context.Args().First()
|
|
force := context.Bool("force")
|
|
container, err := getContainer(context)
|
|
if err != nil {
|
|
if errors.Is(err, libcontainer.ErrNotExist) {
|
|
// if there was an aborted start or something of the sort then the container's directory could exist but
|
|
// libcontainer does not see it because the state.json file inside that directory was never created.
|
|
path := filepath.Join(context.GlobalString("root"), id)
|
|
if e := os.RemoveAll(path); e != nil {
|
|
fmt.Fprintf(os.Stderr, "remove %s: %v\n", path, e)
|
|
}
|
|
if force {
|
|
return nil
|
|
}
|
|
}
|
|
return err
|
|
}
|
|
s, err := container.Status()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
switch s {
|
|
case libcontainer.Stopped:
|
|
destroy(container)
|
|
case libcontainer.Created:
|
|
return killContainer(container)
|
|
default:
|
|
if force {
|
|
return killContainer(container)
|
|
}
|
|
return fmt.Errorf("cannot delete container %s that is not stopped: %s\n", id, s)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|