Feeds:
Posts
Comments

Posts Tagged ‘processmutex’

I’m a huge fan of code reuse, and I tend to trust other people’s public code more than my own private code. After all, if they put effort into making it public, they must have put a lot of thought into it. And more than likely it is probably their speciality. That’s why I don’t (for example) implement my own webservers :) Having said that, I’ve reimplemented more wheels than I care to admit. Here is me, providing my own version of identity – a built-in emacs function. How embarrassing. Almost put me off blogging that did.

So, I try to do a bit of due dilligence when I’m thinking about writing a simple thing that someone surely has already done. What I want, is an interprocess mutex. There must be a million ways of doing these things, so I have a quick look on CPAN. Searching for mutex brings up LockFile::NetLock which looks interesting (although slightly paranoid, and I don’t have my own ftp server).

IPC::Semaphore looks like it only supports SysV (i.e. not Windows) and the API is somewhat baroque. Win32::Semaphore has the opposite problem (I’m guessing). I did like the look of POSIX::RT::Semaphore but suspected it wouldn’t install on Windows.

dmake.EXE:  Error code 129, while making 'Semaphore.o'
  MJP/POSIX-RT-Semaphore-0.05.tar.gz
  C:\strawberry\c\bin\dmake.EXE -- NOT OK
Running make test
  Can't test without successful make
Running make install
  Make had returned bad status, install seems impossible

Yep, I was right. I’ll spare you the results from the other hour I spent googling various things like semaphore and process mutex.

Okay, let’s think about this. Maybe I could write my own simple little thing with a nice API, and if I find a decent module later I can delegate to it, or maybe delegate to Win32::Semaphore on Windows and the SysV version everywhere else. The ACE guys call that a wrapper facade. Does flock work on Windows?

So the plan is to call flock LOCK_EX on a file in the constructor, and then flock LOCK_UN in the destructor in a kinda RAII way. Famous last words, but what else could I possibly need?

package IPC::ProcessMutex;

use Carp;
use Fcntl;

sub import { }

sub new
{
    my $class = shift;
    my $file = shift;

    my $fh;
    if (! sysopen($fh, $file, O_CREAT)) {
        croak "Unable to sysopen $file";
    }

    my $self = { handle => $fh };
    bless $self, $class;

    flock $fh, Fcntl::LOCK_EX;

    return $self;
}

sub DESTROY
{
    my $self = shift;

    if (exists $self->{handle}) {
        flock $self->{handle}, Fcntl::LOCK_UN;
        close $self->{handle};
        delete $self->{handle};
    } else {
        carp 'DESTROY - handle was not defined';
    }
}

1;

And to avoid having to think to hard about whether the code actually works or not, I’ll check it with a little test ;)

use POSIX;
use FindBin;

use lib "$FindBin::Bin/lib/perl5";

use IPC::ProcessMutex;

sub my_log
{
    my $ts = POSIX::strftime('%H:%M:%S', localtime(time()));
    print "[ $ts ] : ", @_, "\n";
}

{
    my_log 'Getting mutex ...';
    my $mutex = IPC::ProcessMutex->new('.filename.lock');
    my_log 'Got mutex.  Sleeping 10 ...';
    sleep 10;
}

my_log 'Released mutex.';

Process 1

jared@win32 $ perl get-mutex.pl
[ 21:37:57 ] : Getting mutex ...
[ 21:37:57 ] : Got mutex.  Sleeping 10 ...
[ 21:38:07 ] : Released mutex.
jared@win32 $ perl get-mutex.pl
[ 21:38:15 ] : Getting mutex ...
[ 21:38:17 ] : Got mutex.  Sleeping 10 ...
[ 21:38:27 ] : Released mutex.
jared@win32 $

Process 2

jared@win32 $ perl get-mutex.pl
[ 21:38:02 ] : Getting mutex ...
[ 21:38:07 ] : Got mutex.  Sleeping 10 ...
[ 21:38:17 ] : Released mutex.
jared@win32 $ perl get-mutex.pl
[ 21:38:24 ] : Getting mutex ...
[ 21:38:27 ] : Got mutex.  Sleeping 10 ...
[ 21:38:37 ] : Released mutex.
jared@win32 $

Yes! Mission accomplished as they say. I’m tentatively going to go with that…

Read Full Post »

Follow

Get every new post delivered to your Inbox.