예제 #1
0
func (d *directProcess) watch(cmd *exec.Cmd, exitSubscription *subreaper.Subscription) {
	defer subreaper.Unsubscribe(exitSubscription)
	defer d.delete()

	f, err := os.OpenFile(path.Join(d.root, ExitFile), syscall.O_WRONLY, 0)
	if err == nil {
		defer f.Close()
	}

	exitCode := 0
	if err = cmd.Wait(); err != nil {
		if exitError, ok := err.(exec.ExitCodeError); ok {
			exitCode = exitError.Code
		}
	}

	if exitCode == 0 {
		pid, err := d.getPidFromFile()
		if err != nil {
			return
		}
		exitSubscription.SetPid(pid)
		exitCode = exitSubscription.Wait()
	}

	writeInt(path.Join(d.root, ExitStatusFile), exitCode)
}
예제 #2
0
func (d *directProcess) Start() error {
	cwd, err := filepath.Abs(d.root)
	if err != nil {
		return err
	}

	stdin, stdout, stderr, err := d.openIO()
	if err != nil {
		return nil
	}

	checkpoint, err := d.loadCheckpoint(d.container.bundle)
	if err != nil {
		return err
	}

	logPath := filepath.Join(cwd, "log.json")
	args := append([]string{
		"--log", logPath,
		"--log-format", "json",
	}, d.container.runtimeArgs...)
	if d.exec {
		args = append(args, "exec",
			"--process", filepath.Join(cwd, "process.json"),
			"--console", d.consolePath,
		)
	} else if checkpoint != nil {
		args = append(args, "restore",
			"--image-path", filepath.Join(d.container.bundle, "checkpoints", checkpoint.Name),
		)
		add := func(flags ...string) {
			args = append(args, flags...)
		}
		if checkpoint.Shell {
			add("--shell-job")
		}
		if checkpoint.Tcp {
			add("--tcp-established")
		}
		if checkpoint.UnixSockets {
			add("--ext-unix-sk")
		}
		if d.container.noPivotRoot {
			add("--no-pivot")
		}
	} else {
		args = append(args, "start",
			"--bundle", d.container.bundle,
			"--console", d.consolePath,
		)
		if d.container.noPivotRoot {
			args = append(args, "--no-pivot")
		}
	}
	args = append(args,
		"-d",
		"--pid-file", filepath.Join(cwd, "pid"),
		d.container.id,
	)
	cmd := exec.Command(d.container.runtime, args...)
	cmd.Dir = d.container.bundle
	cmd.Stdin = stdin
	cmd.Stdout = stdout
	cmd.Stderr = stderr
	// set the parent death signal to SIGKILL so that if containerd dies the container
	// process also dies
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Pdeathsig: syscall.SIGKILL,
	}

	exitSubscription := subreaper.Subscribe()
	err = d.startCmd(cmd)
	if err != nil {
		subreaper.Unsubscribe(exitSubscription)
		d.delete()
		return err
	}

	go d.watch(cmd, exitSubscription)

	return nil
}