Code hangs when writing log message to text file by multiple source using Perl Script

195 views Asked by At

I am using below code to write log message to text file, the program is getting hanged when different source calls this method in parallel. Is there a way to grant /control parallel writing without breaking the program.

sub sLog {
    my $self = 'currentServerDirectory';
    my $logMsg = "";

    my $fileName = join '_', $self->{LogFilePrefix}, &sTimeStamp("Log");
    my $absFileName = "$self->{LogFolder}/$fileName.txt";

        open APPHDLER, ">>$absFileName" or &exitErr("Cannot append message to file, $absFileName");
        print APPHDLER scalar(localtime(time))." - $logMsg\n";
        close APPHDLER;
}
2

There are 2 answers

3
jamie On

When you open a file for writing, a lock on that file is granted to the process that opened it. This is done to prevent corruption of data, by processes overwriting each other. Possible solutions would be to feed the output data to a single process that handles writing to the log file, making sure that processes close the file and release their locks when they are finished writing, or using a library or file format that is designed for parallel access of files. The first two of those methods would be the easiest and preferred for writing log files like this. There are also probably perl modules (check CPAN) that handle log files.

0
Automaton On

Try using flock -- here is a simple example you can try to understand its behavior:

use strict;
use warnings;
use Fcntl qw/:flock/;

chomp(my $id = `date`);
my $cnt = 0;
while (1) {
    open LOG, ">>shared" or die "Couldn't open shared";
    flock (LOG, LOCK_EX) or die "Couldn't flock";
    print LOG "$id: $cnt\n";
    $cnt++;
    sleep 1;
    close LOG;
}

Say this is saved in flock.pl, then you can run flock.pl& to run one or more instances in the background. Then do tail -f shared to see what happens. Since you are sleeping 1 second between obtaining the lock and releasing it via close LOG , you'll see an update once a second if you have one process. However, if you have N processes, you'll see each one taking N seconds.

In your existing example, you can try adding the use Fcntl and flock lines.