Golang Non Blocking os.Stdin Read for Cmd

173 Views Asked by At
cmd := exec.Command("env")
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout

This works well regardless env command doesn't relay on reading from stdin

Yet for

cmd := exec.Command("env")
reader, writer := os.Pipe()
go func() {
  io.Copy(writer, os.Stdin)
  reader.Close()
}()
cmd.Stdin = reader
cmd.Stdout = os.Stdout

It executes env command well but next blocks until whatever input is made (regardless env doesn't need it)

Even such would reproduce the situation

cmd := exec.Command("env")
cmd.Stdin = struct{io.Reader}{os.Stdin}
cmd.Stdout = os.Stdout

But this actually reproduces the Pipe flow under the hood of Cmd implementation it self once the Stdin is not *os.File (see code )

    if f, ok := c.Stdin.(*os.File); ok {
        return f, nil
    }

    pr, pw, err := os.Pipe()
    if err != nil {
        return nil, err
    }
    ...

So wat is the basic difference here as io.Copy says it should behave the very same way

Copy copies from src to dst until either EOF is reached on src or an error occurs

So what is the diff on providing directly os.Stdin to piping it over intermediate Reader. And how to make a Pipe approach behave the same non blocking way

My actual case is even more complex as it pipes the stdin over a net.Conn still I hope the. understanding of described behavior would give me the same clue for the solution.

Thx.

0

There are 0 best solutions below