3

In a nutshell: wrote a Perl script using flock(). On Linux, it behaves as expected. On AIX, flock() always returns 1, even though another instance of the script, using flock(), should be holding an exclusive lock on the lockfile.

We ship a Bash script to restart our program, relying on flock(1) to prevent simultaneous restarts from making multiple processes. Recently we deployed on AIX, where flock(1) doesn't come by default and won't be provided by the admins. Hoping to keep things simple, I wrote a Perl script called flock, like this:

#!/usr/bin/perl

use Fcntl ':flock';
use Getopt::Std 'getopts';

getopts("nu:x:");

%switches = (LOCK_EX => $opt_x, LOCK_UN => $opt_u, LOCK_NB => $opt_n);

my $lockFlags = 0;

foreach $key (keys %switches) {
    if($switches{$key}) {$lockFlags |= eval($key)};
}

$fileDesc = $opt_x || $opt_u;

open(my $lockFile, ">&=$fileDesc") ||  die "Can't open file descriptor: $!";
flock($lockFile, $lockFlags) || die "Can't change lock - $!\n";;

I tested the script by running (flock -n -x 200; sleep 60)200>lockfile twice, nearly simultaneously, from two terminal tabs.

On Linux, the second run dies with "Resource temporarily unavailable", as expected.

On AIX, the second run acquires the lock, with flock() returning 1, as most definitely not expected.

I understand the flock() is implemented differently on the two systems, the Linux version using flock(1) and the AIX one using, I think, fcntl(1). I don't have enough expertise to understand how this causes my problem, and how to solve it.

Many thanks for any advice.

Thomas Heywood
  • 903
  • 2
  • 9
  • 18

2 Answers2

2

It's not about different commands, I suppose; it's more about global differences between AIX and Linux.

In POSIX systems, file locks are advisory: each program could check the file's state and then reconsider what has to be done with it. No explicit checks = no locking.

In Linux systems, however, one can try to enforce a mandatory lock, although the doc itself states that it would be unwise to rely on it: implementation is (and probably will ever be) buggy.

Therefore, I suggest implementing such checks of advisory flags within the script itself.

More about it: man 2 fcntl, man 2 flock.

raina77ow
  • 103,633
  • 15
  • 192
  • 229
  • Not sure I follow you, sorry. I expect advisory locking from Perl's flock() (is this correct?), regardless of the underlying architecture, as long as there's some kind of advisory locking. I'm also unsure what you mean by "checks of advisory flags." Anyway, thanks for the reply! – Thomas Heywood Apr 27 '12 at 11:06
2

This isn't anything to do with AIX, the open() call in your script is incorrect.

Should should be something like:

open (my $lockfile, ">>", $fileDesc) # for LOCK_EX, must be write

You were using the "dup() previously opened file handle" syntax with >&=, but the script had not opened any files to duplicate, nor should it.

My quick tests shows the correct behavior (debugging added)

first window:
$ ./flock.pl -n -x lockfile
opened lockfile
locked
second window:
$./flock.pl -n -x lockfile
opened lockfile
Can't change lock - Resource temporarily unavailable
$
CoreyStup
  • 1,488
  • 13
  • 14
  • You also don't need to include Fnctl":flock", as flock() is a valid C runtime function that perl will use natively. – CoreyStup Apr 27 '12 at 22:26
  • CoreyStup: the include gives me handy constants - LOCK_EX and the like. – Thomas Heywood Apr 30 '12 at 07:20
  • Thanks for the detailed reply. I had used >&= because the intended use of my script was to lock on a file descriptor for a file opened in Bash, like so: (flock.pl -x 200; do_stuff)200>lockfile. It does work on Linux as intended. – Thomas Heywood Apr 30 '12 at 07:26