On Sat, Jun 01, 2024 at 09:20:59AM +0200, DdB wrote:
> > #!/bin/bash -e
> > 
> > coproc { bash; }
> > exec 5<&${COPROC[0]} 6>&${COPROC[1]}
> > fd=5
> > 
> > echo "ls" >&6
> > while IFS= read -ru $fd line
> > do
> >     printf '%s\n' "$line"
> > done
> > 
> > printf "%s\n" "sleep 3;exit" >&6
> > while IFS= read -ru $fd line
> > do
> >     printf '%s\n' "$line"
> > done
> > 
> > exec 5<&- 6>&-
> > 
> > wait
> > echo waited, done
> 
> i get the output from ls, but then the thing is hanging indefinitely,
> apparently not reaching the exit line. :(

Your first while loop never terminates.  "while read ..." continues
running until read returns a nonzero exit status, either due to an
error or EOF.  Your coproc never returns EOF, so the "while read"
loop just keeps waiting for the next line of output from ls.

If you're going to communicate with a long-running process that can
return multiple lines of output per line of input, then you have
three choices:

  1) Arrange for some way to communicate how many lines, or bytes,
     of output are going to be given.

  2) Send a terminator line (or byte sequence) of some kind that
     indicates "end of current data set".

  3) Give up and assume the end of the data set after a certain amount
     of time has elapsed with no new output arriving.  (This is usually
     not the best choice.)

These same design issues occur in any kind of network communication, too.
Imagine an IMAP client or something, which holds open a network connection
to its IMAP server.  The client asks for the body of an email message,
but needs to keep the connection open afterward so that it can ask for
more things later.  The server has to be able to send the message back
without closing the connection at the end.  Therefore, the IMAP protocol
needs some way to "encapsulate" each server response, so the client
knows when it has received the full message.

Reply via email to