Sys::Tlock - Locking with timeouts.
1.11
use Sys::Tlock;
# Taking a tlock for 5 minutes, in that diectory.
tlock_take('maint',300,dir=>'/var/logsystem/locks/')
or die 'Failed taking the tlock.';
my $token = $_;
move_old_index();
# Hand over to that other script.
exec( '/usr/local/logrotate/logrotate.pl' , $token );
-----------------------------------------------------------
use Sys::Tlock
dir => '/var/logsystem/locks/' ,
owner => scalar getpwnam('logsystem') ,
qw(tlock_release tlock_renew $patience);
print "tlock patience is ${patience}\n";
# Checking that tlock is alive.
my $t = $ARGV[0];
die 'Tlock not taken.' if not tlock_alive('maint',$t);
# Make time for fancy rotation task.
tlock_renew('maint',600);
do_fancy_log_rotation(547);
# Call another script that requires this tlock.
system( './clean-up.sh' , $t );
# Releasing the tlock.
tlock_release('maint',$t);
This module is handling tlocks, advisory locks with timeouts.
It is designed to allow separate programs to use the same tlocks between them. Even programs written in different languages. To do this safely, each tlock is paired with a token.
The tlocks are simply living in a lock directory in the filesystem. A distant predecessor to this module was written as a kludge to make locking work properly on a Windows server. But it turned out to be very handy to have tlocks in the filesystem, giving you an at-a-glance overview of them. And giving the non-scripting sysadmins easy access to view and manipulate them.
The module might die on compile-time errors. It will not die on runtime errors. Runtime errors might return error values, might warn or might be ignored, whatever should be the most sensible for the particular error.
Each configuration parameter is set by the top most line that apply:
-
- In a call, as named parameter with name "dir", "marker", "owner" or "patience".
-
- Configuration file given in a call by a named parameter with the name "conf".
-
- Directly in the use statement of your script, with key "dir", "marker", "owner" or "patience".
-
- Configuration file given by a "conf" key in the use statement of your script.
-
- Environment variable "tlock_dir", "tlock_marker", "tlock_owner" or "tlock_patience".
-
- Configuration file given by the environment variable "tlock_conf".
-
- Configuration file "/etc/tlock.conf".
-
- Default configuration.
On top of this, you can import the $dir, $marker, $owner and $patience variables and change them in your script. But that is a recipe for disaster, so know what you do, if you go that way.
Configuration files must start with a "tlock 1" line. Empty lines are allowed and so are comments starting with the # character. There are four directives:
dir
For setting the lock directory. Write the full path.
marker
For the marker (prefix) that all tlock directory names will get.
owner
For the UID of the owner that will be set for tlock directories.
patience
For the time that a call will wait for a tlock release.
tlock 1
# Example configuration file for tlock.
dir /var/loglocks/
patience 7.5
Safe use of tlocks involve tokens, which are just timestamps of when the tlock was taken.
Without tokens, something like this could happen...
script1 takes lockA
script1 freezes
lockA times out
script2 takes lockA
script1 resumes
script1 releases lockA
script3 takes lockA
Now both script2 and script3 "have" lockA!
Each tlock is a subdirectory of the lock directory. Their names are "${marker}.${label}". The default value for $marker is "tlock".
All the data for a tlock is in its directory. If it is removed from the lock directory, the tlock is released. If it is moved back in, it is alive again (unless it has timed out). If too much playing around has messed up the lock directory, running tlock_zing on it cleans it up.
The lock directory also contains shortlived directories named "${marker}_.${label}". They are per label master locks that help to make changes to the tlocks atomic.
Loaded by default: tlock_take, tlock_renew, tlock_release, tlock_alive, tlock_taken, tlock_expiry, tlock_zing
Loaded on demand: tlock_tstart, tlock_release_careless, tlock_token, $dir, $marker, $owner, $patience
-
tlock_take( $label , $timeout )
Take the tlock with the given label, and set its timeout. The call returns the associated token. The token value is also assigned to the $_ variable.
Labels can be any non-empty string consisting of letters a-z or A-Z, digits 0-9, dashes "-", underscores "_" and dots "." (PCRE: [a-zA-Z0-9\-\_\.]+)
For backwards compatibility, it is possible to write tlock_take($l,$t,patience => $p) as tlock_take($l,$t,$p) instead. But it is deprecated and will issue a warning.
-
tlock_renew( $label , $token , $timeout )
Reset the timeout of the tlock, so that it will time out $timeout seconds from the time that tlock_renew is called.
-
tlock_release( $label , $token )
Release the tlock.
-
tlock_alive( $label , $token )
Returns true if the tlock is currently taken.
-
tlock_taken( $label )
Returns true if a tlock with the given label is currently taken.
The difference between tlock_taken and tlock_alive, is that alive can differentiate between different tlocks with the same label. Different tlocks with the same label can exist at different points in time.
-
tlock_expiry( $label )
Returns the time when the current tlock with the given label will expire. It is given in epoch seconds.
-
tlock_zing()
Cleans up tlocks in the lock directory. Takes care not to mess with any lock activity.
-
tlock_tstart( $label )
Returns the time for the creation of the current tlock with the given label. It is given in epoch seconds. This function and the token function are identical.
Only loaded on demand.
-
tlock_release_careless( $label )
Carelessly release any tlock with the given label, not caring about the token.
Only loaded on demand.
-
tlock_token( $label )
Returns the token for the current tlock with the given label.
Only loaded on demand.
-
$dir
The directory containing the tlocks.
Only loaded on demand.
-
$marker
The common prefix of the directory names used for tlocks.
Prefixes can be any non-empty string consisting of letters a-z or A-Z, digits 0-9, dashes "-" and underscores "_" (PCRE: [a-zA-Z0-9\-\_]+). First character has to be a letter, and last character a letter or digit.
Only loaded on demand.
-
$owner
The UID of the owner of the tlocks.
Will be silently ignored if it cannot be set.
Default value is -1. Which means the owner running the script.
Only loaded on demand.
-
$patience
Patience is the number of seconds a call will try to take or change a tlock, before it gives up. For example when tlock_take tries to take a tlock that is already taken, it is the number of seconds it should wait for that tlock to be released before giving up.
Patience can be set to any non-negative fractional number. If it is set to 0, a call only tries once before giving up.
Dont confuse patience with timeout.
Default patience value is 0.
Only loaded on demand.
All the tlock subroutines can be given optional named parameters. They must be written after the mandatory parameters. The names can be "conf", "dir", "marker", "owner" and "patience". See the CONFIGURATION chapter for more details.
File::Basename
Time::HiRes
The author dare not guarantee that the locking is waterproof. But if there are conditions that breaks it, they must be very special. At the least, experience has shown it to be waterproof in practice.
Not tested on Windows, ironically enough.
flock
(c) 2022-2023 Bjoern Hee
Licensed under the Apache License, version 2.0