Subject: | tests broken on BSD due to tempfile locking conflict |
Hi Brad,
With the following system:
Brackup 1.03
sqlite 3.3.17
DBD-SQLite 1.13
DBI 1.57
perl v5.8.8 built for amd64-freebsd
FreeBSD 6.1-RELEASE on amd64
Running 'make test' fails like so:
# make test
PERL_DL_NONLAZY=1 /usr/local/bin/perl "-MExtUtils::Command::MM" "-e"
"test_harness(0, 'blib/lib', 'blib/arch')" t/*.t
t/00-use.....................ok
t/01-backup..................ok 1/12Error: DBD::SQLite::db do failed:
database is locked(5) at dbdimp.c line 271 at
/usr/ports/sysutils/p5-Brackup/work/Brackup-1.03/blib/lib/Brackup/Dict/SQLite.pm
line 19.
# Looks like you planned 12 tests but only ran 1.
# Looks like your test died just after 1.
t/01-backup..................dubious
Test returned status 255 (wstat 65280, 0xff00)
DIED. FAILED tests 2-12
Failed 11/12 tests, 8.33% okay
t/02-gpg.....................ok 1/12Error: DBD::SQLite::db do failed:
database is locked(5) at dbdimp.c line 271 at
/usr/ports/sysutils/p5-Brackup/work/Brackup-1.03/blib/lib/Brackup/Dict/SQLite.pm
line 19.
# Looks like you planned 12 tests but only ran 1.
# Looks like your test died just after 1.
t/02-gpg.....................dubious
Test returned status 255 (wstat 65280, 0xff00)
DIED. FAILED tests 2-12
Failed 11/12 tests, 8.33% okay
t/03-combine-little-files....ok 1/15Error: DBD::SQLite::db do failed:
database is locked(5) at dbdimp.c line 271 at
/usr/ports/sysutils/p5-Brackup/work/Brackup-1.03/blib/lib/Brackup/Dict/SQLite.pm
line 19.
# Looks like you planned 15 tests but only ran 1.
# Looks like your test died just after 1.
t/03-combine-little-files....dubious
Test returned status 255 (wstat 65280, 0xff00)
DIED. FAILED tests 2-15
Failed 14/15 tests, 6.67% okay
Failed Test Stat Wstat Total Fail List of Failed
-------------------------------------------------------------------------------
t/01-backup.t 255 65280 12 22 2-12
t/02-gpg.t 255 65280 12 22 2-12
t/03-combine-little-files.t 255 65280 15 28 2-15
Failed 3/4 test scripts. 36/40 subtests failed.
Files=4, Tests=40, 91 wallclock secs ( 0.63 cusr + 0.16 csys = 0.79 CPU)
Failed 3/4 test programs. 36/40 subtests failed.
*** Error code 255
Stop in /usr/ports/sysutils/p5-Brackup/work/Brackup-1.03.
What's happening is BSD implements open(2)'s O_EXLOCK flag, which causes
File::Temp::tempfile to obtain an exclusive lock on the temporary files
it creates. When Brackup's tests make a tempfile and later try to create
a database there, the tempfile lock conflicts with the exclusive lock
that DBD::SQLite::db desires.
Attached is a hacky fix: have Brackup::Util::tempfile release the lock
(if any) obtained by File::Temp::tempfile(). There does not seem to be a
way to tell File::Temp::tempfile to not use O_EXLOCK, so some platforms
will get a lock and others won't and it isn't documented. :(
Alternatively you could roll your own tempfile routine using one of the
lower-level system calls like POSIX::tmpnam.
With this change, plus the hardwired path to gpg customized for FreeBSD,
the tests pass.
Thanks for Brackup, I'm looking forward to trying it out!
--Matt, http://fjarlq.livejournal.com/
Subject: | brackuplock.diff |
--- lib/Brackup/Util.pm.orig Wed May 23 15:28:52 2007
+++ lib/Brackup/Util.pm Wed Jul 18 20:52:09 2007
@@ -20,9 +20,15 @@
}
}
use File::Temp ();
+use Fcntl ':flock'; # import LOCK_* constants
sub tempfile {
my (@ret) = File::Temp::tempfile();
+
+ # On some systems, File::Temp::tempfile locks the file using O_EXLOCK.
+ # Abandon any such lock, as it will conflict with database use.
+ flock($ret[0], LOCK_UN);
+
my $from = join(" ", (caller())[0..2]);
push @TEMP_FILES, [$ret[1], $from];
return wantarray ? @ret : $ret[0];