Reading Stdout from a Subprocess

I am trying to create a subprocess from Golang. The goal is to read and process input in turn. Here is what I am trying to get:

func readStuff(scanner *bufio.Scanner) { for scanner.Scan() { fmt.Println("Performed Scan") fmt.Println(scanner.Text()) } if err := scanner.Err(); err != nil { fmt.Fprintln(os.Stderr, "reading standard input:", err) } } func main() { cmd := exec.Command("/usr/local/bin/pocketsphinx_continuous", "-inmic", "yes") out, err := cmd.StdoutPipe() err = cmd.Start() checkError(err) scanner := bufio.NewScanner(out) fmt.Println("Scanner created") defer cmd.Wait() go readStuff(scanner) } 

In this example, "Created Scanner" is printed, but nothing happens after that.

Running this command, however, leads to what I expect to print:

 /usr/local/bin/pocketsphinx_continuous -inmic yes 1>out.txt 

And also changing the code for direct copying to stdout also works:

 cmd := exec.Command("/usr/local/bin/pocketsphinx_continuous", "-inmic", "yes") cmd.Stdout = os.Stdout 

What am I missing, what prevents me from reading the result?

+8
go
source share
2 answers

There are a few things you can check out.

  • The error code returned by cmd.StdoutPipe() is not checked. It should be.

  • The pocketsphinx_continuous requires the -hmm and -dict . Otherwise, it will fail, and all output is actually sent to stderr , not stdout . Here you only read stdout , but there is nothing to read.

  • You should not call cmd.Wait() before making sure that all data has been read from stdout . The result is not deterministic (in fact, this is a race condition). Check the documentation for the os/exec package. If you absolutely need parsing to be done in goroutine, you need to synchronize it with the end of goroutine before calling cmd.Wait() . For example, you can write a function as:

     func readStuff(scanner *bufio.Scanner, stop chan bool) { // Scanning code // ... stop<-true } 

    and the main code:

     stop := make(chan bool) go readStuff(scanner,stop) <-stop cmd.Wait() 
+4
source share

You don't seem to need

 go readStuff(scanner) 

due to

 cmd.Start() 

make a system plug so simple

 readStuff(scanner) 

It would be enough for my mind (this does not require promotion)

0
source share

All Articles