A trick with perl

Chris Fortune cfortune at telus.net
Sun Jan 4 23:46:14 CET 2004


*In PERL/Linux, I am attempting to emulate `bogofilter < email.txt`, but
using a ram file (FIFO pipe) rather than a disc file.  Reason, so
'email.txt' can be input on STDIN to several different programs, which all
output to STDOUT, and to do it with minimal (or no) disc access.  If anyone
has other perl-ish ideas, please post them.*

"Andrew Pimlott" <andrew at pimlott.net> wrote:
> That's great, but I'm fairly sure it is not possible with the code
> you posted.  One, you created the "fifo" with "mknod $file b", which
> is not correct.

Yes, true, 'system("mknod filename.txt b");' produces a usage error, but
works anyways!  Using mknod with the 'b' option creates a "block special
file"  Such devices can be read a "block" (many characters) at a time, thus
buffering data in main memory until a reader is attached.  You are supposed
to give two numbers as command-line options, the "major and minor device
numbers", but without them, it defaults to main memory, which is where we
want it to reside anyways.  (If anyone has the major and minor numbers for a
RAM drive, I would appreciate being able to call it explicitly, rather than
relying on mknod's default behaviour.)

> Two, I had forgotten that even an open for write on
> a fifo will block until a reader is attached.  So the code you
> posted can't even make it past the open call.

What is blocked is the FIFO process, not the calling program.  The code
works.

> Anyhow, I'm glad it works, but it is good to be aware of the
> possibility for deadlock when using pipes.

Yes, thanks for the reminder!  There should be an insurance subroutine that
traps $SIG{PIPE} signals.
$SIG{PIPE} = \&pipeHandler;
sub pipeHandler {
    my $sig = shift @_;
    print " Caught SIGPIPE: $sig $1 \n";
    exit(1);
}

Cautious programers may want to put the entire input/output procedure in an
eval{} block, with an alarm.

thanks






More information about the Bogofilter mailing list