# LOCKING
-fcntl(2) locking exclusively locks the empty $GIT_DIR/ssoma.lock file
+flock(2) locking exclusively locks the empty $GIT_DIR/ssoma.lock file
for all non-atomic operations.
# EXAMPLE INPUT FLOW (SERVER-SIDE MDA)
2. Mail transport agent invokes ssoma-mda
3. reads message via stdin, extracting Message-ID
-4. acquires fcntl lock on $GIT_DIR/ssoma.lock
+4. acquires exclusive flock lock on $GIT_DIR/ssoma.lock
5. creates or updates the blob of associated 2/38 SHA-1 path
6. updates the index and commits
7. releases $GIT_DIR/ssoma.lock
: The normal git index (in $GIT_DIR/index) is not used at all as
there is typically no working tree.
-* $GIT_DIR/ssoma.lock - empty file for fcntl(2) locking
+* $GIT_DIR/ssoma.lock - empty file for flock(2) locking
: This is necessary to ensure the index and commits are updated
consistently and multiple processes running MDA do not step on
each other.
- Digest::SHA perl
- Email::LocalDelivery libemail-localdelivery-perl
- Email::Simple libemail-simple-perl
- - File::FcntlLock libfile-fcntllock-perl
- File::Path::Expand libfile-path-expand-perl
- Net::IMAP::Simple libnet-imap-simple-perl
'Digest::SHA' => 0,
'Email::LocalDelivery' => 0,
'Email::Simple' => 0,
- 'File::FcntlLock' => 0,
'File::Path::Expand' => 0,
'Net::IMAP::Simple' => 0,
},
* MTA - postfix is recommended
* Perl and several modules:
- Email::Simple
- - File::FcntlLock
- Digest::SHA
Hacking
use strict;
use warnings;
use File::Path qw/mkpath/;
+use Fcntl qw/:DEFAULT :flock SEEK_END/;
use IO::Handle;
-use Fcntl;
-use File::FcntlLock;
use Email::Simple;
use Digest::SHA qw/sha1_hex/;
sub sync_do {
my ($self, $sub) = @_;
- my $fs = File::FcntlLock->new;
- $fs->l_type(F_WRLCK);
- $fs->l_type(SEEK_CUR);
- $fs->l_start(0);
- $fs->l_len(0);
-
my $path = $self->lockfile;
my $lock;
die "failed to open lock $path: $!\n";
# wait for other processes to be done
- $fs->lock($lock, F_SETLKW) or die "lock failed: " . $fs->error . "\n";
+ flock($lock, LOCK_EX) or die "lock failed: $!\n";
# run the sub!
my @ret = eval { &$sub };
my $err = $@;
# these would happen anyways, but be explicit so we can detect errors
- $fs->lock($lock, F_UNLCK) or die "unlock failed: " . $fs->error . "\n";
+ flock($lock, LOCK_UN) or die "unlock failed: $!\n";
close $lock or die "close lockfile($path) failed: $!\n";
die $err if $err;