(ctx context.Context, container containerd.Container, id string, opts execOptions)
| 110 | } |
| 111 | |
| 112 | func (c *criService) execInternal(ctx context.Context, container containerd.Container, id string, opts execOptions) (*uint32, error) { |
| 113 | // Cancel the context before returning to ensure goroutines are stopped. |
| 114 | // This is important, because if `Start` returns error, `Wait` will hang |
| 115 | // forever unless we cancel the context. |
| 116 | ctx, cancel := context.WithCancel(ctx) |
| 117 | defer cancel() |
| 118 | |
| 119 | var drainExecSyncIOTimeout time.Duration |
| 120 | var err error |
| 121 | |
| 122 | if c.config.DrainExecSyncIOTimeout != "" { |
| 123 | drainExecSyncIOTimeout, err = time.ParseDuration(c.config.DrainExecSyncIOTimeout) |
| 124 | if err != nil { |
| 125 | return nil, fmt.Errorf("failed to parse drain_exec_sync_io_timeout %q: %w", |
| 126 | c.config.DrainExecSyncIOTimeout, err) |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | spec, err := container.Spec(ctx) |
| 131 | if err != nil { |
| 132 | return nil, fmt.Errorf("failed to get container spec: %w", err) |
| 133 | } |
| 134 | task, err := container.Task(ctx, nil) |
| 135 | if err != nil { |
| 136 | return nil, fmt.Errorf("failed to load task: %w", err) |
| 137 | } |
| 138 | pspec := spec.Process |
| 139 | |
| 140 | pspec.Terminal = opts.tty |
| 141 | if opts.tty { |
| 142 | if err := oci.WithEnv([]string{"TERM=xterm"})(ctx, nil, nil, spec); err != nil { |
| 143 | return nil, fmt.Errorf("add TERM env var to spec: %w", err) |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | pspec.Args = opts.cmd |
| 148 | // CommandLine may already be set on the container's spec, but we want to only use Args here. |
| 149 | pspec.CommandLine = "" |
| 150 | |
| 151 | if opts.stdout == nil { |
| 152 | opts.stdout = cio.NewDiscardLogger() |
| 153 | } |
| 154 | if opts.stderr == nil { |
| 155 | opts.stderr = cio.NewDiscardLogger() |
| 156 | } |
| 157 | execID := util.GenerateID() |
| 158 | log.G(ctx).Debugf("Generated exec id %q for container %q", execID, id) |
| 159 | volatileRootDir := c.getVolatileContainerRootDir(id) |
| 160 | var execIO *cio.ExecIO |
| 161 | |
| 162 | process, err := task.Exec(ctx, execID, pspec, |
| 163 | func(id string) (containerdio.IO, error) { |
| 164 | cntr, err := c.containerStore.Get(container.ID()) |
| 165 | if err != nil { |
| 166 | return nil, fmt.Errorf("an error occurred when try to find container %q: %w", container.ID(), err) |
| 167 | } |
| 168 | sb, err := c.sandboxStore.Get(cntr.SandboxID) |
| 169 | if err != nil { |
no test coverage detected