....funny no one mentioned that you can share a filehandle between threads thru the fileno, see FileHandles and threads...here is an old node..... just put the logfile's fileno into a shared variable....then any thread can open it...... watch out for concurrency problems though
#!/usr/bin/perl
use warnings;
use strict;
use threads;
use threads::shared;
# original idea from BrowserUK at
# http://perlmonks.org?node_id=493754
for my $file ( map{ glob $_ } @ARGV ) {
open my $fh, '<', $file or warn "$file : $!" and next;
printf "From main: %s", scalar <$fh> for 1 .. 10;
printf "Fileno:%d\n", fileno $fh;
threads->create( \&thread, fileno( $fh ) )->detach;
printf 'paused:';<STDIN>;
}
sub thread{
my( $fileno ) = @_;
open my $fh, "<&=$fileno" or warn $! and die;
printf "%d:%s", threads->self->tid, $_ while defined( $_ = <$fh> );
close $fh;
}
...this bit of code might interest you
========
zentara wrote:
> I wouldn't give up too quickly on letting the threads close and
> rename the file.
>
> First, all threads share the same filehandles thru the filenos.
[snipped outline for shared writing to logfile]
Heureka!
My problem was not getting the logging sorted out. I didn't think that
+
you could close the filehandle from each thread. But one is actually
required to, before the file is free to rename. I should have tried it
+
before.
Thanks for your input!
Thomas
Here a small example that works as intended:
use strict;
use warnings;
use threads;
use Thread::Queue;
use IO::File;
my $q = Thread::Queue->new();
sub worker {
my $fh;
while (1) {
my $fno = $q->dequeue();
if ( $fno ) {
print "worker: opening fileno:$fno\n";
$fh = IO::File->new_from_fd($fno, '>') or die $!;
$fh->autoflush(1);
print $fh "worker was here\n";
} else {
$fh->close();
}
}
}
threads->new(\&worker)->detach();
my $fname = 'test.log';
my $fh;
$fh = IO::File->new($fname, '>') or die $!;
$fh->autoflush(1);
print $fh "main was here\n";
$q->enqueue($fh->fileno());
sleep 1;
$q->enqueue(0);
sleep 1;
$fh->close();
rename($fname, "$fname.1") or die $!;
$fh = IO::File->new($fname, '>') or die $!;
$fh->autoflush(1);
print $fh "main was here\n";
$q->enqueue($fh->fileno());
sleep 1;
|