Skip to content

proposal: os/exec: add Cmd.Clone method #77075

@adonovan

Description

@adonovan

Background: a recent change to exec.Cmd made it stricter about detecting the misuse of the API that arises when Start is called again after a first call failed (see #76746). Though this defensive behavior change clearly falls within the original documented intent of the API, it has caused a number of latent misuses to show up in Google code as dynamic errors. (We should probably also improve the go1.26 release notes to provide warning of this friction.)

Most of the errors, though not all, can be avoided relatively easily by rewriting the logic to create a new Cmd instead of reusing the old one. Generally this involves making a shallow copy of all exported fields: cmd = &exec.Cmd{Path: cmd.Path, Args: cmd.Args, ...}. However, this kind of logic is fragile because the addition of a new exported field to Cmd would require a corresponding update to this copy statement, which is almost certain to be forgotten (different authors, different code base, version skew), leading to a latent bug. Also, not all configuration fields of the struct are public: for example, the ctx field is populated only by the CommandContext constructor, is not exported, and is not accessible through any method. This means there is currently no way to write the correct logic to fully copy the Cmd; more invasive restructuring of the application may be required to plumb the required context.

Proposal: We propose to add a Clone method to Cmd that returns a new Cmd that is a copy of the old one w.r.t. all its configuration but on which Start may be safely called.

package exec // "os/exec"

// Clone returns a new Cmd that is a copy of the old one with respect to
// its configuration, and on which Start has never been called.
func (*Cmd) Clone() *Cmd

@prattmic @lfolger

Metadata

Metadata

Assignees

No one assigned

    Labels

    LibraryProposalIssues describing a requested change to the Go standard library or x/ libraries, but not to a toolProposal

    Type

    No type

    Projects

    Status

    Active

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions