#!/usr/bin/perl use strict; use warnings; # import LOCK_* use Fcntl qw(:flock); my $lockbase = shift; # suggested: $GL_REPO_BASE/$GL_REPO.git/.gl-mirror-push-lock.$COPY_NAME my @cmd_plus_args = @ARGV; # the actual 'gitolite mirror ...' command @ARGV = (); # ---------------------------------------------------------------------- open( my $fhrun, ">", "$lockbase.run" ) or die "open '$lockbase.run' failed: $!"; if ( flock( $fhrun, LOCK_EX | LOCK_NB ) ) { # got run lock; you're good to go system(@cmd_plus_args); flock( $fhrun, LOCK_UN ); exit 0; } # "run" lock failed; someone is already running the command open( my $fhqueue, ">", "$lockbase.queue" ) or die "open '$lockbase.queue' failed: $!"; if ( flock( $fhqueue, LOCK_EX | LOCK_NB ) ) { # got queue lock, now block waiting for "run" lock flock( $fhrun, LOCK_EX ); # got run lock, so take yourself out of "queue" state, then run flock( $fhqueue, LOCK_UN ); system(@cmd_plus_args); flock( $fhrun, LOCK_UN ); exit 0; } # "queue" lock also failed; someone is running AND someone is queued; we can go home say STDERR "INFO: nothing to do/queue; '$lockbase' already running and 1 in queue"; exit 0;