| John Saalwaechter 2004-03-27, 12:01 am |
| In a perl script, I need to run a task on a regular interval,
and also respond to other asynchronous events without waiting.
My thought was to make a named pipe, and then use select()
on it with a timeout. If the asynchronous event occurred,
another process could drop a signal message into the named
pipe, and my perl script would return from select() immediately.
If no asynchronous event occurred, then the select() timeout
would occur and the script could perform the periodic task
before going back in to the select().
I found lots of bits of information in the perldocs and by
googling, but no good explicit examples. There is one major
bit that's hard to locate: you need to open the named pipe
as read/write. I finally got it all straightened out, so in
the hope of saving someone else the search grief, here is a
full example of using select() on a fifo:
#!/usr/bin/perl -Tw
#
# Example script that uses select() with
# a timeout on a named pipe.
#
use strict;
my $interval=10; # seconds
my $fifo="/tmp/testfifo"; # create from shell with "mkfifo /tmp/testfifo"
if (!(-p $fifo && -w _ && -r _))
{
print STDERR "Bad fifo $fifo!\n";
exit(1);
}
# Open the fifo read/write, not just read. This is necessary because
# of the POSIX rules about using select() on named pipes when no writers
# are present. This is a very key step that is hard to find documentation
# about.
open(FIFOFH,"+<",$fifo) || die $!;
while(1)
{
my $rin='';
vec($rin,fileno(FIFOFH),1)=1;
my $nfound=select($rin,undef,undef,$interva
l);
print "It is now ",scalar(localtime),"\n";
if($nfound)
{
my $fifodata=<FIFOFH>;
print $fifodata,"\n";
}
# Do some other periodic tasks here...
}
__END__
|