On Mon, Jun 04, 2012 at 07:17:57PM +0200, Raphael Hertzog wrote:
> Hi,
> 
> On Mon, 04 Jun 2012, Dominic Hargreaves wrote:
> > The attached patch solves this by using flock() which is built into
> > perl, rather than an external library. My understanding is that this
> > should be adequate for the purpose, but please let me know if I've missed
> > something and there is a strong reason to use File::FcntlLock instead
> > (if so, maybe we could make the relationship to libfile-fcntllock-perl a
> > recommends, and abort if we detect that a parallel build is being invoked
> > without File::FcntlLock being installed).
> 
> There was a reason, reviewing
> http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=642608 tells you that
> we wanted locking to work on NFS too, so we wanted to use
> fcntl()-based locking instead of flock()-based locking.
> 
> And using fcntl() directly from Perl is difficult. Quoting Guillem:
> | to lock using fcntl(2) the function needs a struct flock which would
> | need to be packed from the perl code, but the order of its members is not
> | standardized anywhere, and sizeof(off_t) might vary, that's what seems
> | tricky to me.
> 
> I think that we probably want to abstract the locking code and use
> File::FcntlLock when available and fallback to flock() otherwise so that
> we can demote it to Recommends.

Okay, this makes sense.

I've revised the patch accordingly and attached it.

I wasn't sure if the small amount of code which could be factored out
justified a new file (and couldn't see an exisiting one), so I left it
in the scripts. Happy to refactor into a new or existing file if you
let me know your preference.

Cheers,
Dominic.

-- 
Dominic Hargreaves | http://www.larted.org.uk/~dom/
PGP key 5178E2A5 from the.earth.li (keyserver,web,email)
>From 1a85392f99ba56dd95d9274a31577c3403120c99 Mon Sep 17 00:00:00 2001
From: Dominic Hargreaves <d...@earth.li>
Date: Mon, 4 Jun 2012 12:11:46 +0100
Subject: [PATCH] Fallback to flock when needed

libfile-fcntllock-perl build-depends on dpkg-dev, so avoid this circular
build-dependency by only libfile-fcntllock-perl and falling back to using
flock when File::FcntlLock is not available.
---
 debian/control              |    5 +++--
 scripts/dpkg-distaddfile.pl |   18 ++++++++++++++----
 scripts/dpkg-gencontrol.pl  |   18 ++++++++++++++----
 3 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/debian/control b/debian/control
index 3184473..62e36f7 100644
--- a/debian/control
+++ b/debian/control
@@ -51,9 +51,10 @@ Section: utils
 Priority: optional
 Architecture: all
 Multi-Arch: foreign
-Depends: libdpkg-perl (= ${source:Version}), libfile-fcntllock-perl, bzip2, xz-utils,
+Depends: libdpkg-perl (= ${source:Version}), bzip2, xz-utils,
  patch, make, binutils, base-files (>= 5.0.0), ${misc:Depends}
-Recommends: gcc | c-compiler, build-essential, fakeroot, gnupg, gpgv, libalgorithm-merge-perl
+Recommends: gcc | c-compiler, build-essential, fakeroot, gnupg, gpgv, libalgorithm-merge-perl,
+ libfile-fcntllock-perl
 Suggests: debian-keyring
 Breaks: dpkg-cross (<< 2.0.0), devscripts (<< 2.10.26)
 Description: Debian package development tools
diff --git a/scripts/dpkg-distaddfile.pl b/scripts/dpkg-distaddfile.pl
index 5d80d5e..f39347c 100755
--- a/scripts/dpkg-distaddfile.pl
+++ b/scripts/dpkg-distaddfile.pl
@@ -20,7 +20,7 @@
 use strict;
 use warnings;
 
-use File::FcntlLock;
+use Fcntl qw(:flock);
 use POSIX;
 use POSIX qw(:errno_h :signal_h);
 use Dpkg;
@@ -77,12 +77,22 @@ my ($file, $section, $priority) = @ARGV;
 
 # Obtain a lock on debian/control to avoid simultaneous updates
 # of debian/files when parallel building is in use
-my $fs = File::FcntlLock->new(l_type => F_WRLCK);
 my $lockfh;
 sysopen($lockfh, "debian/control", O_WRONLY) ||
     syserr(_g("cannot write %s"), "debian/control");
-$fs->lock($lockfh, F_SETLKW) ||
-    syserr(_("failed to get a write lock on %s"), "debian/control");
+
+# dpkg-dev only Recommends libfile-fcntllock-perl to allow 
+# libfile-fcntllock-perl to be rebuilt
+eval { require File::FcntlLock };
+if ($@) {
+    warning(_g("File::FcntlLock not available; using flock which is not NFS-safe"));
+    flock($lockfh, LOCK_EX) ||
+        syserr(_("fcntl: failed to get a write lock on %s"), "debian/control");
+} else {
+    my $fs = File::FcntlLock->new(l_type => F_WRLCK);
+    $fs->lock($lockfh, F_SETLKW) ||
+        syserr(_("flock: failed to get a write lock on %s"), "debian/control");
+}
 
 $fileslistfile="./$fileslistfile" if $fileslistfile =~ m/^\s/;
 open(Y, "> $fileslistfile.new") || syserr(_g("open new files list file"));
diff --git a/scripts/dpkg-gencontrol.pl b/scripts/dpkg-gencontrol.pl
index 103a276..c4b1ebb 100755
--- a/scripts/dpkg-gencontrol.pl
+++ b/scripts/dpkg-gencontrol.pl
@@ -22,7 +22,7 @@
 use strict;
 use warnings;
 
-use File::FcntlLock;
+use Fcntl qw(:flock);
 use POSIX;
 use POSIX qw(:errno_h);
 use Dpkg;
@@ -336,12 +336,22 @@ for my $f (keys %remove) {
 
 # Obtain a lock on debian/control to avoid simultaneous updates
 # of debian/files when parallel building is in use
-my $fs = File::FcntlLock->new(l_type => F_WRLCK);
 my $lockfh;
 sysopen($lockfh, "debian/control", O_WRONLY) ||
     syserr(_g("cannot write %s"), "debian/control");
-$fs->lock($lockfh, F_SETLKW) ||
-    syserr(_("failed to get a write lock on %s"), "debian/control");
+
+# dpkg-dev only Recommends libfile-fcntllock-perl to allow 
+# libfile-fcntllock-perl to be rebuilt
+eval { require File::FcntlLock };
+if ($@) {
+    warning(_g("File::FcntlLock not available; using flock which is not NFS-safe"));
+    flock($lockfh, LOCK_EX) ||
+        syserr(_("fcntl: failed to get a write lock on %s"), "debian/control");
+} else {
+    my $fs = File::FcntlLock->new(l_type => F_WRLCK);
+    $fs->lock($lockfh, F_SETLKW) ||
+        syserr(_("flock: failed to get a write lock on %s"), "debian/control");
+}
 
 $fileslistfile="./$fileslistfile" if $fileslistfile =~ m/^\s/;
 open(Y, ">", "$fileslistfile.new") || syserr(_g("open new files list file"));
-- 
1.7.10

Reply via email to