There might be. Or I might be holding it wrong. I'm about to post another thread with a different angle on this. This thread was mis-framed.
On Mon, Jun 17, 2024 at 1:16 PM Harri L <harl...@gmail.com> wrote: > I’m wondering if there’s a specific reason you’re using io.Pipe instead > of the Cmd.StdoutPipe helper? When using io.Pipe you need to Close the > pipe by yourself, but when using the Cmd.StdoutPipe, the Cmd.Wait will > close the pipe for you. > > Here’s a sample following your previous example: > func main() { defer err2.Catch() cmdName := "/bin/sh" cmdArgs := []string{ > "-c", "for i in 1 2 3 4 5 6 7 8 9 10; do echo step $i; sleep 0.1; done", > } cmd := exec.CommandContext(context.Background(), cmdName, cmdArgs...) > stdoutPipe := try.To1(cmd.StdoutPipe()) var wg sync.WaitGroup go > readPipe(stdoutPipe, &wg) try.To(cmd.Start()) wg.Wait() try.To(cmd.Wait()) > fmt.Println("DONE") } func readPipe(src io.Reader, wg *sync.WaitGroup) { > defer err2.Catch() wg.Add(1) defer wg.Done() buf := make([]byte, 256) for > eof, n := try.IsEOF1(src.Read(buf)); !eof; eof, n = > try.IsEOF1(src.Read(buf)) { try.To1(os.Stdout.Write(buf[:n])) } } > > And here’s a sample using io.Pipe; please see the noted line: > func main() { defer err2.Catch() cmdName := "/bin/sh" cmdArgs := []string{ > "-c", "for i in 1 2 3 4 5 6 7 8 9 10; do echo step $i; sleep 0.1; done", > } cmdStdoutR, cmdStdoutW := io.Pipe() cmd := > exec.CommandContext(context.Background(), cmdName, cmdArgs...) cmd.Stdout = > cmdStdoutW var wg sync.WaitGroup go readPipe(cmdStdoutR, &wg) > try.To(cmd.Run()) cmdStdoutW.Close() // NOTE: needed for io.Pipe ↓ > fmt.Println("DONE") wg.Wait() } > > On Monday, June 17, 2024 at 6:21:13 AM UTC+3 Salvatore Domenick Desiano > wrote: > >> Ah! >> >> I apologize... in reducing it to a compact example I didn't notice that I >> changed the semantics of what the code was doing. You are, of course, right >> about the cause of the deadlock in this code. >> >> That said, working backward from the self-contained example to my full >> code clarified the actual issue I'm debugging. It is sufficiently different >> from what I said here that I will start a new thread if I can't figure it >> out myself. >> >> Thank you! >> >> -- Salvatore >> smile. >> >> >> On Sun, Jun 16, 2024 at 10:35 PM Robert Engels <ren...@ix.netcom.com> >> wrote: >> >>> It hangs because cmd.Run() waits for the process to complete - and with >>> nothing reading the pipe it will never complete. >>> >>> On Jun 16, 2024, at 9:33 PM, Robert Engels <ren...@ix.netcom.com> wrote: >>> >>> >>> It looks like you don’t have anything reading from the pipe so it’s >>> going to hang. >>> >>> On Jun 16, 2024, at 8:54 PM, Salvatore Domenick Desiano < >>> near...@gmail.com> wrote: >>> >>> >>> Simpler self-contained example, same result: >>> >>> func main() { >>> >>> cmdName := "/bin/bash" >>> cmdArgs := []string{"-c", "while true; do echo step; sleep 1; done"} >>> >>> cmdStdoutR, cmdStdoutW := io.Pipe() >>> cmd := exec.Command(cmdName, cmdArgs...) >>> cmd.Stdout = cmdStdoutW >>> if err := cmd.Run(); err != nil { >>> >>> fmt.Println(err) >>> >>> } >>> fmt.Println("DONE") >>> >>> cmdStdoutR = cmdStdoutR >>> >>> } >>> >>> For the sake of completeness I'll mention that this runs fine if >>> cmd.Stdout is not assigned, which points to exec.awaitGoroutines() as being >>> the culprit. >>> >>> FWIW, I have no direct evidence that the pipes aren't being closed on >>> the SIGKILL. That said, the (exec-internal) goroutines are hung on >>> io.Copy(). I expect that if the process's output pipe was actually closed >>> the io.Copy() would return, the goroutine would complete, and the deadlock >>> would not happen. >>> >>> -- Salvatore >>> smile. >>> >>> >>> On Sun, Jun 16, 2024 at 7:58 PM Salvatore Domenick Desiano < >>> near...@gmail.com> wrote: >>> >>>> I hope this isn't a red herring but in constructing a self-contained >>>> example I triggered a deadlock. Perhaps the deadlock is the answer to my >>>> question or perhaps it is another issue. Either way this code does not seem >>>> malformed: >>>> >>>> func main() { >>>> >>>> cmdName := "/bin/bash" >>>> cmdArgs := []string{ >>>> >>>> "-c", >>>> >>>> "while true; do echo step; sleep 1; done", >>>> >>>> } >>>> cmdStdinR, cmdStdinW := io.Pipe() >>>> cmdStdoutR, cmdStdoutW := io.Pipe() >>>> cmdStderrR, cmdStderrW := io.Pipe() >>>> ctx, cancelCmd := context.WithCancel(context.Background()) >>>> cmd := exec.CommandContext(ctx, cmdName, cmdArgs...) >>>> cmd.Stdin = cmdStdinR >>>> cmd.Stdout = cmdStdoutW >>>> cmd.Stderr = cmdStderrW >>>> >>>> if err := cmd.Start(); err != nil { >>>> >>>> fmt.Println(err) >>>> >>>> } >>>> >>>> cmdStdinW.Close() >>>> if err := cmd.Wait(); err != nil { >>>> >>>> fmt.Println(err) >>>> >>>> } >>>> >>>> fmt.Println("DONE") >>>> >>>> cancelCmd = cancelCmd >>>> cmdStdoutR = cmdStdoutR >>>> cmdStderrR = cmdStderrR >>>> >>>> } >>>> >>>> If you run this code and SIGKILL the bash process, go flags it as a >>>> deadlock and panics. FWIW, this also happens if there are goroutines >>>> monitoring cmdStdoutR and cmdStderrR. >>>> >>>> What am I missing? >>>> >>>> -- Salvatore >>>> smile. >>>> >>>> >>>> -- >>> 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. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/golang-nuts/CAEQs7S-Gwuvh8MJ48Nv1Cwd7miHiUX4RdwKjqmeLqMBcWYYgJQ%40mail.gmail.com >>> <https://groups.google.com/d/msgid/golang-nuts/CAEQs7S-Gwuvh8MJ48Nv1Cwd7miHiUX4RdwKjqmeLqMBcWYYgJQ%40mail.gmail.com?utm_medium=email&utm_source=footer> >>> . >>> >>> -- > 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. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/782a2013-703d-451c-9567-7be585d17c5fn%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/782a2013-703d-451c-9567-7be585d17c5fn%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- 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. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEQs7S_E38ostoY_0ybNqHvMuT7tLgM%3DqUBbvzB4bgAePiAjDg%40mail.gmail.com.