The open fails if the child process cannot be created. If the command
itself does not exist or exits erroneously, this will (generally) not
be seen as an error when opening, but as an error when closing.
We'll get to that in a moment.
For all intents and purposes, the rest of the program doesn't
know, doesn't care, and would have to work pretty hard to
figure out that this is a filehandle opened on a process rather than
on a file. So, to get data from a filehandle opened for reading,
we'll just do the normal read:
my $now = <DATE>;
And to send data to the mail process (waiting for the body of a
message to deliver to merlyn on standard input),
a simple print-with-a-filehandle will do:
print MAIL "The time is now $now"; # presume $now ends in newline
In short, you can pretend that these filehandles are hooked up to
magical files, one that contains the output of the
date command, and one that will automatically be
mailed by the mail command.
If a process is connected to a filehandle that is open for reading,
and then exits, the filehandle returns end-of-file, just like reading
up to the end of a normal file. When you close a filehandle open for
writing to a process, the process will see end-of-file. So, to finish
sending the email, close the handle:
close MAIL;
die "mail: non-zero exit of $?" if $?;
Closing a filehandle attached to a process waits for the process to
complete, so that Perl can get the process's exit status. The
exit status is then available in the $? variable
(reminiscent of the same variable in the Bourne Shell), and is the
same kind of number as the value returned by the
system function: zero for success, nonzero for
failure. Each new exited process overwrites the previous value
though, so save it quickly if you want it. (The $?
variable also holds the exit status of the most recent
system or backquoted command, if you're
curious.)
The processes are synchronized just like a pipelined command. If you
try to read and no data is available, the process is suspended
(without consuming additional CPU time) until the sending program has
started speaking again. Similarly, if a writing process gets ahead of
the reading process, the writing process is slowed down until the
reader starts to catch up. There's a buffer (usually 4K bytes
or so) in between so they don't have to stay precisely in lock
step.
Why use processes as filehandles? Well, it's the only easy way
to write to a process based on the results of a computation. But if
you're just reading, backquotes are often much easier to
manage, unless you want to have the results as they come in.