exec.Cmd: if the child forks Wait may hang forever

2,359 views
Skip to first unread message

noxiouz

unread,
Jul 13, 2016, 4:50:56 PM7/13/16
to golang-nuts
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!



 

Ian Lance Taylor

unread,
Jul 13, 2016, 5:05:41 PM7/13/16
to noxiouz, golang-nuts
On Wed, Jul 13, 2016 at 1:50 PM, noxiouz <tyurin...@gmail.com> wrote:
>
> I faced a corner case of cmd.Exec usage and want to find out if it's
> designed behavior.

...

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

Sounds like https://golang.org/issue/13155 .

Ian

Steven Hartland

unread,
Jul 13, 2016, 5:10:02 PM7/13/16
to golan...@googlegroups.com
If your forked process still has stdin / stdout open then I would say this is expected.

You could confirm this by adding the following to the python script.
import sys
...
if pid == 0:
   sys.stdin.close()
   sys.stdout.close()
--
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...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

noxiouz

unread,
Jul 13, 2016, 5:18:22 PM7/13/16
to golang-nuts, ste...@multiplay.co.uk
The question it not about how to fork properly =)

I really simplified the script. Actually I have to exec code, that I do not control.

For me the both usages look the same.
Of course, to be on the safe side I am going to use StdoutPipe way, but it looks like a bug for me. At least, I have no way to interrupt the waiting process.

четверг, 14 июля 2016 г., 0:10:02 UTC+3 пользователь Steven Hartland написал:

noxiouz

unread,
Jul 13, 2016, 5:49:16 PM7/13/16
to golang-nuts
https://github.com/golang/go/blob/master/src/os/exec/exec.go#L484 set io.Writer explicitly so it looks like a bug

среда, 13 июля 2016 г., 23:50:56 UTC+3 пользователь noxiouz написал:
Reply all
Reply to author
Forward
0 new messages