mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
fdb100d247
We need to make sure the container is destroyed before closing the stdio for the container. This becomes a big issues when running in the host's pid namespace because the other processes could have inherited the stdio of the initial process. The call to close will just block as they still have the io open. Calling destroy before closing io, especially in the host pid namespace will cause all additional processes to be killed in the container's cgroup. This will allow the io to be closed successfuly. This change makes sure the order for destroy and close is correct as well as ensuring that if any errors encoutered during start or exec will be handled by terminating the process and destroying the container. We cannot use defers here because we need to enforce the correct ordering on destroy. This also sets the subreaper setting for runc so that when running in pid host, runc can wait on the addiontal processes launched by the container, useful on destroy, but also good for reaping the additional processes that were launched. Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
124 lines
3.2 KiB
Go
124 lines
3.2 KiB
Go
// +build linux
|
|
|
|
package main
|
|
|
|
import (
|
|
"os"
|
|
"runtime"
|
|
|
|
"github.com/codegangsta/cli"
|
|
"github.com/coreos/go-systemd/activation"
|
|
"github.com/opencontainers/runc/libcontainer"
|
|
"github.com/opencontainers/specs/specs-go"
|
|
)
|
|
|
|
// default action is to start a container
|
|
var startCommand = cli.Command{
|
|
Name: "start",
|
|
Usage: "create and run a container",
|
|
ArgsUsage: `<container-id>
|
|
|
|
Where "<container-id>" is your name for the instance of the container that you
|
|
are starting. The name you provide for the container instance must be unique on
|
|
your host.`,
|
|
Description: `The start command creates an instance of a container for a bundle. The bundle
|
|
is a directory with a specification file and a root filesystem.`,
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "bundle, b",
|
|
Value: "",
|
|
Usage: `path to the root of the bundle directory, defaults to the current directory`,
|
|
},
|
|
cli.StringFlag{
|
|
Name: "console",
|
|
Value: "",
|
|
Usage: "specify the pty slave path for use with the container",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "detach,d",
|
|
Usage: "detach from the container's process",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "pid-file",
|
|
Value: "",
|
|
Usage: "specify the file to write the process id to",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "no-subreaper",
|
|
Usage: "disable the use of the subreaper used to reap reparented processes",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) {
|
|
bundle := context.String("bundle")
|
|
if bundle != "" {
|
|
if err := os.Chdir(bundle); err != nil {
|
|
fatal(err)
|
|
}
|
|
}
|
|
spec, err := loadSpec(specConfig)
|
|
if err != nil {
|
|
fatal(err)
|
|
}
|
|
|
|
notifySocket := os.Getenv("NOTIFY_SOCKET")
|
|
if notifySocket != "" {
|
|
setupSdNotify(spec, notifySocket)
|
|
}
|
|
|
|
if os.Geteuid() != 0 {
|
|
fatalf("runc should be run as root")
|
|
}
|
|
|
|
status, err := startContainer(context, spec)
|
|
if err != nil {
|
|
fatal(err)
|
|
}
|
|
// exit with the container's exit status so any external supervisor is
|
|
// notified of the exit with the correct exit status.
|
|
os.Exit(status)
|
|
},
|
|
}
|
|
|
|
var initCommand = cli.Command{
|
|
Name: "init",
|
|
Usage: `init is used to initialize the containers namespaces and launch the users process.
|
|
This command should not be called outside of runc.
|
|
`,
|
|
Action: func(context *cli.Context) {
|
|
runtime.GOMAXPROCS(1)
|
|
runtime.LockOSThread()
|
|
factory, _ := libcontainer.New("")
|
|
if err := factory.StartInitialization(); err != nil {
|
|
fatal(err)
|
|
}
|
|
panic("libcontainer: container init failed to exec")
|
|
},
|
|
}
|
|
|
|
func startContainer(context *cli.Context, spec *specs.Spec) (int, error) {
|
|
id := context.Args().First()
|
|
if id == "" {
|
|
return -1, errEmptyID
|
|
}
|
|
container, err := createContainer(context, id, spec)
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
detach := context.Bool("detach")
|
|
// Support on-demand socket activation by passing file descriptors into the container init process.
|
|
listenFDs := []*os.File{}
|
|
if os.Getenv("LISTEN_FDS") != "" {
|
|
listenFDs = activation.Files(false)
|
|
}
|
|
r := &runner{
|
|
enableSubreaper: !context.Bool("no-subreaper"),
|
|
shouldDestroy: true,
|
|
container: container,
|
|
listenFDs: listenFDs,
|
|
console: context.String("console"),
|
|
detach: detach,
|
|
pidFile: context.String("pid-file"),
|
|
}
|
|
return r.run(&spec.Process)
|
|
}
|