Repository: moby/moby
File: daemon/exec.go (Go)

Code before:
	}

	if ec.OpenStdin {
		ec.StreamConfig.NewInputPipes()
	} else {
		ec.StreamConfig.NewNopInputPipe()
	}

	p := &specs.Process{}
	if runtime.GOOS != "windows" {
		// TODO(thaJeztah): also enable on Windows;
		//  This was added in https://github.com/moby/moby/commit/7603c22c7365d7d7150597fe396e0707d6e561da,
		//  which mentions that it failed on Windows "Probably needs to wait for container to be in running state"
		ctr, err := daemon.containerdClient.LoadContainer(ctx, ec.Container.ID)
		if err != nil {
			return err
		}
		md, err := ctr.Info(ctx, containerd.WithoutRefreshedMetadata)
		if err != nil {
			return err
		}

		// Technically, this should be a [specs.Spec], but we're only
		// interested in the Process field.
		spec := &struct{ Process *specs.Process }{p}
		if err := json.Unmarshal(md.Spec.GetValue(), spec); err != nil {
			return err
		}
	}

	// merge/override properties of the container's process with the exec-config.
	p.Args = append([]string{ec.Entrypoint}, ec.Args...)
	p.Env = ec.Env
	p.Cwd = ec.WorkingDir
	p.Terminal = ec.Tty

	consoleSize := options.ConsoleSize
	// If size isn't specified for start, use the one provided for create
	if consoleSize == nil {
		consoleSize = ec.ConsoleSize
	}
	if p.Terminal && consoleSize != nil {
		p.ConsoleSize = &specs.Box{
			Height: consoleSize[0],
			Width:  consoleSize[1],
		}
	}

	if p.Cwd == "" {
		p.Cwd = "/"
	}

Review comment (suggestion):
IIUC, the intent here is to update fields of `p` according to the JSON content of "process" in `md.Spec.GetValue()` and the `spec` itself is not used at later point.

nit:
```suggestion
		spec := struct{ Process *specs.Process }{p}
		if err := json.Unmarshal(md.Spec.GetValue(), &spec); err != nil {
```

I think this makes more sense - we only need the address for the `json.Unmarshal`, we don't care if `spec` itself is a value or pointer.

Code after:
	if ec.OpenStdin && options.Stdin != nil {
		r, w := io.Pipe()
		go func() {
			defer func() {
				log.G(ctx).Debug("Closing buffered stdin pipe")
				_ = w.Close()
			}()
			_, _ = pools.Copy(w, options.Stdin)
		}()
		cStdin = r
	}
	if ec.OpenStdout {
		cStdout = options.Stdout
	}
	if ec.OpenStderr {
		cStderr = options.Stderr
	}

	if ec.OpenStdin {
		ec.StreamConfig.NewInputPipes()
	} else {
		ec.StreamConfig.NewNopInputPipe()
	}

	p := &specs.Process{}
	if runtime.GOOS != "windows" {
		// TODO(thaJeztah): also enable on Windows;
		//  This was added in https://github.com/moby/moby/commit/7603c22c7365d7d7150597fe396e0707d6e561da,
		//  which mentions that it failed on Windows "Probably needs to wait for container to be in running state"
		ctr, err := daemon.containerdClient.LoadContainer(ctx, ec.Container.ID)
		if err != nil {
			return err
		}
		md, err := ctr.Info(ctx, containerd.WithoutRefreshedMetadata)
		if err != nil {
			return err
		}

		// Technically, this should be a [specs.Spec], but we're only
		// interested in the Process field.
		spec := struct{ Process *specs.Process }{p}
		if err := json.Unmarshal(md.Spec.GetValue(), &spec); err != nil {
			return err
		}
	}

	// merge/override properties of the container's process with the exec-config.
	p.Args = append([]string{ec.Entrypoint}, ec.Args...)
	p.Env = ec.Env
	p.Cwd = ec.WorkingDir
	p.Terminal = ec.Tty