Skip Menu |

This queue is for tickets about the BerkeleyDB_Locks CPAN distribution.

Report information
The Basics
Id: 11064
Status: new
Priority: 0/
Queue: BerkeleyDB_Locks

People
Owner: Nobody in particular
Requestors: vkvask [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: (no value)
Fixed in: (no value)



Subject: Does not detect *all* WAIT locks in DB-Locks_0_4
- Platform: Solaris 5.8 - DB: Berkeley DB 4.2 with BerkeleyDB module 0.26 - Distribution Name: BerkeleyDB-Locks_0_4 I was hoping to use BerkeleyDB-Locks_0_4 in my implementation where there are multiple processes (Apache) using a BerkeleyDB. Every once in a while, when a process dies, it leaves behind a WAIT lock. However, this Locks package does not remove *all* WAIT locks. In some situations I can clearly see that there are locks (using the "db_stat -Co -h /tmp/bdb" command which displays locks in WAIT status) but this package does not see anything as being locked (neither the poll() nor the monitor() methods). To reproduce this issue, I am attaching a test case (test4.pl) that is based mostly on the test.pl testcase that is distributed with the package. Basically, is is the same as test.pl except that the writer is focibly killed (kill -9) after it creates the write lock. This causes a WRITE lock to be left in WAIT state. 4 WRITE 1 WAIT /tmp/bdb/dbmfile.bdb page 1 This lock is killed by the parent process which repeatedly loops calling poll(). However, now the WRITE stays in PENDING state (since the process has been killed) and the reader goes into WAIT state (waiting for the write to finish). 4 WRITE 1 PENDING /tmp/bdb/dbmfile.bdb page 1 2 READ 1 WAIT /tmp/bdb/dbmfile.bdb page 1 So, there is a READ lock created in WAIT state and this READ is completely ignored by BerekeleyDB-Locks. I really like this package and would like to use it. I would greatly appreciate it if someone could fix this issue or perhaps direct me on how to fix it. Thanks!
use BerkeleyDB; use BerkeleyDB::Locks; use strict ; my $flag1 = 'ok'; my $flag2 = 'ok'; my $env = new BerkeleyDB::Env -Home => '/tmp/bdb', -Flags => DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN; if ( !fork ) { my $env = new BerkeleyDB::Env -Home => '/tmp/bdb', -Flags => DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN; ## read lock2 my $db = tie my %db, 'BerkeleyDB::Hash', -Env => $env, -Flags => DB_CREATE, -Filename => '/tmp/bdb/dbmfile.bdb', ; local $SIG{ALRM} = sub { $flag2 = undef } ; $db{test2} = 'failed' ; #print STDERR "R2: db{test2} = " . $db{test2} . "\n"; print stderr "R2: Attempting read lock...\n" ; my ( $k, $v ) ; $k = "test2"; my $c = $db->db_cursor ; $c->c_get( $k, $v, DB_FIRST ) ; print STDERR "R2: Created lock\n"; alarm( 5 ) ; while ( $flag2 ) { sleep 1 ; } alarm( 0 ) ; print STDERR "R2: Alarm - lock removed\n"; ## don't know how to get this to display correctly... print "R2: " . $db{test2} . "\n"; untie %db; exit ; } my $writer2 = 0; if ( !($writer2 = fork) ) { my $env = new BerkeleyDB::Env -Home => '/tmp/bdb', #-Flags => DB_CREATE | DB_INIT_MPOOL | DB_INIT_CDB; -Flags => DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN; ## write lock my $db = tie my %db, 'BerkeleyDB::Hash', -Env => $env, -Flags => DB_CREATE, -Filename => '/tmp/bdb/dbmfile.bdb', ; sleep 1 ; print STDERR "W2: attempting write lock...\n" ; ## this statement blocks print STDERR "W2: db{test2} = " . $db{test2} . "\n"; $db{test2} = 'ok' ; print STDERR "W2: db{test2} = " . $db{test2} . "\n"; untie %db; exit; } sleep 1; print STDERR "Killing writer2\n"; system("kill -9 $writer2"); sleep 2 ; for (my $i = 0; $i < 10; $i++) { print stderr " searching for locks...\n" ; my $watch = new BerkeleyDB::Locks $env; my @locks = $watch->poll(); if (scalar(@locks) > 0) { print stderr sprintf " lock detected: %d\n", $locks[0] ; #$db{test} = 100; $watch->monitor() ; ## comment out the next line to force a test failure push @locks, $watch->monitor() ; #print $locks[0], $locks[2] ) ; print stderr sprintf " lock released: %d\n", $locks[2] ; } sleep 2; } exit();