PrePAN

Sign in to PrePAN

Lock::Socket application lock/mutex module based on sockets

Good

Synopsis

### Function API
use Lock::Socket qw/lock_socket try_lock_socket/;

# Raises exception if cannot lock
my $lock = lock_socket(15151);

# Or just return undef
my $lock2 = try_lock_socket(15151) or
    die "handle your own error";


### Object API
use Lock::Socket;

# Create a socket
my $sock = Lock::Socket->new(port => 15151);

# Lock or raise an exception
$sock->lock;

# Can check its status in case you forgot
my $status = $sock->is_locked; # 1 (or 0)

# Re-locking changes nothing
$sock->lock;

# New lock on same port fails
my $sock2 = Lock::Socket->new(port => 15151);
eval { $sock2->lock }; # exception

# But trying to get a lock is ok
my $status = $sock2->try_lock;       # 0
my $same_status = $sock2->is_locked; # 0

# If you need the underlying filehandle
my $fh = $sock->fh;

# You can manually unlock
$sock->unlock;
# ... or unlocking is automatic on scope exit
undef $sock;

Description

Lock::Socket provides cooperative inter-process locking for applications that need to ensure that only one process is running at a time. This module works by binding an INET socket to a port on a loopback (127.0.0.0/8) address which the operating system conveniently restricts to a single process.

The "lock_socket()" and "try_lock_socket()" functions both take a mandatory port number and an optional IP address as arguments, and return a Lock::Socket object on success. "lock_socket()" will raise an exception if the lock cannot be taken whereas "try_lock_socket()" will return "undef".

Objects are instantiated manually as follows:

Lock::Socket->new(
    port => $PORT, # required
    addr => $ADDR, # defaults to 127.X.Y.1
);

On most systems the $PORT number needs to be greater than 1024 unless you are running as root.

If $ADDR is not provided then it is calculated as follows:

Octet   Value
------  ------------------------------
1       127
2       First byte of user ID
3       Second byte of user ID
4       1

This scheme provides something of an automatic per-user lock for a given $PORT, provided there is no user ID greater than 65536. The calculated address can be read back via the "addr()" method.

As soon as the Lock::Socket object goes out of scope the port is closed and the lock can be obtained by someone else.

If you want to keep holding onto a lock socket after a call to "exec" (perhaps after forking) read about the $^F variable in perlvar, as you have to set it before creating a lock socket to ensure the it will not be closed on exec. See the example/solo file in the distribution for a demonstration:

usage: solo PORT COMMAND...

# terminal 1
example/solo 1414 sleep 10  # Have lock on 127.3.232.1:1414

# terminal 2
example/solo 1414 sleep 10  # bind error

Comments

Please sign up to post a review.