Good day!

I faced a corner case of cmd.Exec usage and want to find out if it's 
designed behavior.


go version go1.6.2 darwin/amd64 and linux
>

Let's assume we use cmd.Exec to start some process, that can fork and dies, 
but the fork will live forever. For example:

#!/usr/bin/env python

import os
import time

pid = os.fork()
if pid == 0:
    while True:
        time.sleep(10)

print "main process has quited"


The real script is much more complicated but it's not important.

Also there is a go code:

package main

import (
    "io"
    "log"
    "os/exec"
)

func main() {
    cmd := exec.Command("./forker.py")
    rd, wr := io.Pipe()
    cmd.Stdout = wr
    go func() {
        b := make([]byte, 100)
        for {
            nn, err := rd.Read(b)
            if nn > 0 {
                log.Printf("%s", b[:nn])
            }
            if err != nil {
                log.Fatal(err)
                return
            }
        }
    }()
    if err := cmd.Start(); err != nil {
        log.Fatal(err)
    }

    log.Printf("PID %d", cmd.Process.Pid)

    if err := cmd.Wait(); err != nil {
        log.Fatal(err)
    }
}

The output would be like this:

2016/07/13 23:40:20 PID 90614
> 2016/07/13 23:40:20 main process has quited
>
 
but the Go process will hang forever, because of waiting on: 
https://github.com/golang/go/blob/release-branch.go1.6/src/os/exec/exec.go#L401
I think, because stdout fd of child process would not be closed .

On the other hand the next code works perfectly and does not hang:

package main

import (
    "log"
    "os/exec"
)

func main() {
    cmd := exec.Command("./forker.py")
    rd, err := cmd.StdoutPipe()
    if err != nil {
        log.Fatal(err)
    }
    go func() {
        b := make([]byte, 100)
        for {
            nn, err := rd.Read(b)
            if nn > 0 {
                log.Printf("%s", b[:nn])
            }
            if err != nil {
                log.Fatal(err)
                return
            }
        }
    }()
    if err := cmd.Start(); err != nil {
        log.Fatal(err)
    }

    log.Printf("PID %d", cmd.Process.Pid)

    if err := cmd.Wait(); err != nil {
        log.Fatal(err)
    }
}


So I would like to find out if setting cmd.Stdout explicitly is not 
expected.


Thanks! 



 

-- 
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