Why wait4 doesn't return even if child process exit?

75 views Asked by At

process A run child process B by exec.Command:

...
child = exec.Command(os.Args[0], append([]string{"-child-process"}, os.Args[1:]...)...)
...
go func() {
    if err := child.Run(); err != nil {
        lg.Printf("child process exited abnormally: %s", err)
    }
    childExit <- struct{}{}
}()

lg.Printf("wait for stop signal")
<-stop

for {
    if err := syscall.Kill(child.Process.Pid, syscall.SIGTERM); err != nil {
        lg.Printf("failed to pass SIGTERM to child process: %s", err)
        time.Sleep(time.Second)
    } else {
        break
    }
}
lg.Printf("wait for child stop signal")
<-childExit
lg.Printf("exit")
os.Exit(child.ProcessState.ExitCode())

process B run child process C with B's stdout and stderr, and send SIGTERM to A

// os.Args len > 1 is confirmed
command.Stdout = os.Stdout
command.Stderr = os.Stderr

if err := command.Start(); err != nil {
    server.ErrResponse(ctx, rsp, err.Error())
    return
}

// send SIGTERM to parent process
ppid := os.Getppid()
err := syscall.Kill(ppid, syscall.SIGTERM)
log.C(ctx).Info("send kill to parent process %d", ppid)
if err != nil {
    server.ErrResponse(ctx, rsp, "Error sending SIGTERM to parent process: %v", err)
    return
}

Now I expect A and B exit normally, and C still running and take over by PID1; but actually, B exit, but A still block on child.Run()

I guess wait4 wait for child process(like B) release its STDOUT and STDIN, but it still be used by C, so I try to comment

command.Stdout = os.Stdout
command.Stderr = os.Stderr

and try progress above again; now it works.

So is my guess right? Any proffness exists? Can I pass current process's stdout and stdin to child process and exit(dup?)?

Thanks!

0

There are 0 answers