On Fri, Sep 29, 2017 at 12:33 PM, Alex Buchanan <buchanae.o...@gmail.com> wrote:
>
> package main
>
> import (
> "bytes"
>   "context"
>   "log"
>   "os/exec"
>   "time"
> )
>
> func main() {
>     var stdout bytes.Buffer
>
>   ctx, cancel := context.WithTimeout(context.Background(), time.Second)
>   defer cancel()
>
>   cmd := exec.CommandContext(ctx, "/bin/sh", "-c", "sleep 10; echo foo")
>   cmd.Stdout = &stdout
>
>   err := cmd.Run()
>   log.Printf("%s, %s, '%s'", err, ctx.Err(), stdout.String())
> }
>
>
> This runs for 10 seconds, but I was expecting 1 second. Can someone help me
> understand what is happening? I think it has something to do with the stdout
> bytes.Buffer?

Yes.  The problem is that when the context passed to CommandContext
expires, it kills the process started by the command, but does not
kill any subprocesses that that command may have started.  So when the
context expires the /bin/sh is killed, but the sleep subprocess is
still running.  Because you use a bytes.Buffer, the program has
created a pipe to capture the standard output of the command.  After
the process dies, cmd.Run is waiting for that pipe to be closed to
make sure that it gathers all the data.  But the pipe is held open by
the sleep subprocess.  It is only after that subprocess exits that the
pipe is closed and your program continues.

Ian

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to