Date: Tue, 10 Jul 2001 21:09:51 -0400
From: Benjamin Goldberg <goldbb2@earthlink.net>
Subject: Re: forking ChangeNotify's
Message-Id: <3B4BA75F.878EA8E8@earthlink.net>

Neil wrote:
> 
> I have a piece of code below that "watches" to see if  a log file on a
> certain machine on our network changes size and outputs (to the
> screen) what the changes are.  Basically a "poor mans tail -f".
> 
> This is great as I *can* output it to  HTML format so I can track this
> log from home etc.
> 
> However - I want to track several logs and while I *can* write several
> scripts - I would like to incorporate all "watching" into one script.
> I was thinking if I had a process that "fork"ed each of the watchers -
> and can kill them when the main script was called to exit. Each
> "watcher" is responsible for carrying out it's own actions (ie
> creating an HTML page, sending an e-mail etc.) and resuming watching.
> 
> I am on a Win32 system. I have not attempted forking yet - but have
> read as much as I can about fork in the docs and several O'Reilly
> books - I am just trying to avoid any heartache and lost time before I
> get there ...LOL
> 
> Any ideas about the "best way" to handle this ?

Win32 does not support real forking, but does manage to simulate it
pretty durn well.  So if you want to use a forking solution, then go
ahead and do it.

#! perl.exe -w
use strict;
use IO::Select;
for my $filename (@ARGV) {
	if( my $pid = fork ) {
		push @children, $pid;
		next;
	}
	die "Couldn't fork: $!\n" unless defined $pid;
	open my $fh, "<", $filename or
		die "Couldn't open $filename: $!";
	seek $fh, my $size = -s $fh;
	my $select = IO::Select->new $fh;
	while( $select->can_read ) {
		$size += read $fh, my $contents, (-s $fh) - $size;
		print $contents;
	}
	die "Error in select: $!\n";
}
while( -1 != my $pid = wait ) {
	for( 0 .. $#children ) {
		next unless $children[$_] == $pid;
		print "Tail on file $ARGV[$_] died: $?\n";
	}
}

Or, you could use the full functionality of select, and avoid forking:

#! perl.exe -w
use strict;
use IO::Select;

my %size;
my $select;
for my $filename (@ARGV) {
	open my $fh, "<", $filename or
		die "Couldn't open $filename: $!";
	seek $fh, $size{$fh} = -s $fh;
	$select->add $fh;
}
while( my @ready = $select->can_read ) {
	for my $fh (@ready) {
		$size{$fh} += 
			read $_, my $contents, (-s $fh) - $size{$fh};
		print $contents;
	}
}
die "Error in select: $!\n";

-- 
The longer a man is wrong, the surer he is that he's right.


