1. 程式人生 > 實用技巧 >kata + docker run & star

kata + docker run & star

func (r *runner) run(config *specs.Process) (int, error) {
    if err := r.checkTerminal(config); err != nil {
        r.destroy()
        return -1, err
    }
    process, err := newProcess(*config)
    if err != nil {
        r.destroy()
        return -1, err
    }
    if len(r.listenFDs) > 0
{ process.Env = append(process.Env, fmt.Sprintf("LISTEN_FDS=%d", len(r.listenFDs)), "LISTEN_PID=1") process.ExtraFiles = append(process.ExtraFiles, r.listenFDs...) } baseFd := 3 + len(process.ExtraFiles) for i := baseFd; i < baseFd+r.preserveFDs; i++ { process.ExtraFiles
= append(process.ExtraFiles, os.NewFile(uintptr(i), "PreserveFD:"+strconv.Itoa(i))) } rootuid, err := r.container.Config().HostRootUID() if err != nil { r.destroy() return -1, err } rootgid, err := r.container.Config().HostRootGID() if err != nil { r.destroy()
return -1, err } var ( detach = r.detach || (r.action == CT_ACT_CREATE) ) // Setting up IO is a two stage process. We need to modify process to deal // with detaching containers, and then we get a tty after the container has // started. handler := newSignalHandler(r.enableSubreaper, r.notifySocket) tty, err := setupIO(process, rootuid, rootgid, config.Terminal, detach, r.consoleSocket) if err != nil { r.destroy() return -1, err } defer tty.Close() switch r.action { case CT_ACT_CREATE: err = r.container.Start(process) case CT_ACT_RESTORE: err = r.container.Restore(process, r.criuOpts) case CT_ACT_RUN: err = r.container.Run(process) default: panic("Unknown action") } if err != nil { r.destroy() return -1, err } if err := tty.waitConsole(); err != nil { r.terminate(process) r.destroy() return -1, err } if err = tty.ClosePostStart(); err != nil { r.terminate(process) r.destroy() return -1, err } if r.pidFile != "" { if err = createPidFile(r.pidFile, process); err != nil { r.terminate(process) r.destroy() return -1, err } } status, err := handler.forward(process, tty, detach) if err != nil { r.terminate(process) } if detach { return 0, nil } r.destroy() return status, err }

func (c *linuxContainer) Start(process *Process) error {
        c.m.Lock()
        defer c.m.Unlock()
        if process.Init {
                if err := c.createExecFifo(); err != nil {
                        return err
                }
        }
        if err := c.start(process); err != nil {
                if process.Init {
                        c.deleteExecFifo()
                }
                return err
        }
        return nil
}

func (c *linuxContainer) Run(process *Process) error {
        if err := c.Start(process); err != nil {
                return err
        }
        if process.Init {
                return c.exec()
        }
        return nil
}

func (s *sandbox) getContainer(id string) (*container, error)

ctr, err := a.sandbox.getContainer(req.ContainerId)

// Shared function between CreateContainer and ExecProcess, because those expect
// a process to be run.
func (a *agentGRPC) execProcess(ctr *container, proc *process, createContainer bool) (err error) {
        if ctr == nil {
                return grpcStatus.Error(codes.InvalidArgument, "Container cannot be nil")
        }

        if proc == nil {
                return grpcStatus.Error(codes.InvalidArgument, "Process cannot be nil")
        }

        // This lock is very important to avoid any race with reaper.reap().
        // Indeed, if we don't lock this here, we could potentially get the
        // SIGCHLD signal before the channel has been created, meaning we will
        // miss the opportunity to get the exit code, leading WaitProcess() to
        // wait forever on the new channel.
        // This lock has to be taken before we run the new process.
        a.sandbox.subreaper.lock()
        defer a.sandbox.subreaper.unlock()

        if createContainer {
                err = ctr.container.Start(&proc.process)
        } else {
                err = ctr.container.Run(&(proc.process))
        }
        if err != nil {
                return grpcStatus.Errorf(codes.Internal, "Could not run process: %v", err)
        }

        // Get process PID
        pid, err := proc.process.Pid()
        if err != nil {
                return err
        }

        proc.exitCodeCh = make(chan int, 1)

        // Create process channel to allow WaitProcess to wait on it.
        // This channel is buffered so that reaper.reap() will not
        // block until WaitProcess listen onto this channel.
        a.sandbox.subreaper.setExitCodeCh(pid, proc.exitCodeCh)

        return nil
}