Added locking to cronbuilder.
authorStanislaw Klekot <dozzie@jarowit.net>
Wed, 6 Jul 2011 11:08:57 +0000 (13:08 +0200)
committerStanislaw Klekot <dozzie@jarowit.net>
Wed, 6 Jul 2011 11:08:57 +0000 (13:08 +0200)
It could be that build procedure takes more time than interval at which
cronbuilder is executed. Cron on its own doesn't provide overlapping
prevention, so it's necessary to built that in to cronbuilder.

cronbuilder

index 68b267d..3a78323 100755 (executable)
@@ -10,6 +10,7 @@ use Cron::Builder::Repo;
 use Cron::Builder qw{spawn};
 use Cwd qw{realpath getcwd};
 use Getopt::Long;
+use Fcntl qw{:flock};
 
 #-----------------------------------------------------------------------------
 
@@ -21,6 +22,29 @@ sub true($) {
 
 #-----------------------------------------------------------------------------
 
+sub run_lock {
+  my ($file) = @_;
+
+  open my $fl, ">", $file
+    or die "Can't open lock file: $!";
+
+  if (not flock $fl, LOCK_EX | LOCK_NB) {
+    close $fl;
+    return undef;
+  }
+
+  return [$fl, realpath($file)];
+}
+
+sub run_unlock {
+  my ($lock) = @_;
+
+  close $lock->[0];
+  unlink $lock->[1];
+}
+
+#-----------------------------------------------------------------------------
+
 sub usage {
   printf "Usage:\n" .
          "  %s [options] working-directory\n\n",
@@ -93,6 +117,12 @@ if (not -f "$workdir/cronbuilder.yaml") {
 }
 chdir $workdir;
 
+my $lock = run_lock("cronbuilder.lock");
+if (not $lock) {
+  # another instance of cronbuilder is running
+  exit 0;
+}
+
 my %config = %{ YAML::LoadFile("cronbuilder.yaml") };
 
 $config{build}{inform}  = "true" if $opts{inform};
@@ -138,6 +168,7 @@ if (true $config{build}{rebuild}) {
 if (not $should_build) {
   # no changes in sources and they shouldn't be rebuilt for each run; nothing
   # is necessary
+  run_unlock($lock);
   exit;
 }
 
@@ -199,6 +230,7 @@ if ($opts{commit}) {
 
   if (not defined $commit_output) {
     # no changes in destination, no need to send e-mail
+    run_unlock($lock);
     exit;
   }
 } else {
@@ -236,6 +268,9 @@ if (true $config{build}{inform}) {
   ;
 }
 
+run_unlock($lock);
+exit;
+
 #-----------------------------------------------------------------------------
 
 __END__