The last three examples involved communication only one direction with the subprocess: Either readOnly or write-only. This arrangement is simple and reliable, and is good when it suffices, but we often need to send information both to and from the subprocess.
Arranging such two-way communication with a Muq subprocess is simple, but when doing so you must always be wary of falling into a deadlock configuration in which both ends of the socket are waiting for the other to send something.
One good way to avoid deadlock is to use separate Muq jobs to read and write the socket. If you are sending long blocks of information each direction, this approach is recommended.
Another way to avoid deadlock is to simply send short one-line queries and responses, and to always wait for the response to one query before sending the next. We will use this approach in this example.
In this example, we show how to use a unix
coprocess as a subroutine: We will define a
process which reads one line, converts it to upper
case, returns the result, and then exits. We will
then write a MUF function which hides the
process of invoking the server, so that we wind up
with a function which to the caller looks much
like stringUpcase
-- but much slower,
since a unix process must be started and stopped
for each call. This is not a practical way to
convert strings to uppercase, of course! But this
might be a practical way to invoke a special
FTP subserver, say, which fetched files on
command from another site and then perhaps loaded
them into the Muq db.
For simplicity, our example function will also assume that the given string contains exactly one newline, at the end of the string, and hence can be trivially read and written as a single line.
In muq/srv/
create a file unix-string-upcase-1
with
contents
#!/usr/local/bin/perl $_ = <STDIN>; tr/a-z/A-Z/; print; exit(0);
As usual, at the unix level, do
chmod +x unix-string-upcase-1
to make
the script executable.
Now, at the Muq prompt do:
root: : my-string-upcase-1 { $ -> $ } -> input ;----> makeSocket -> s ;----> makeMessageStream -> i ;----> makeMessageStream -> o ;----> i --> s$S.standardInput ;----> o --> s$S.standardOutput ;----> [ :socket s :commandline "|unix-string-upcase-1|" | ]rootPopenSocket ;----> input i writeStream ;----> o readStreamLine pop ;----> ; root: "abc\n" my-string-upcase-1 root: "ABC "
Fine point: Our my-string-upcase-1
function doesn't bother explicitly closing the
socket. Doing an explicit close would do no
harm, but since our unix-string-upcase-1
program exits
by itself, and since Muq will close the socket
automatically when the associated process exits,
there is no actual need to explicitly close the
socket.
Go to the first, previous, next, last section, table of contents.