Index: lib/Mail/SpamAssassin/BayesStore/DBM.pm =================================================================== --- lib/Mail/SpamAssassin/BayesStore/DBM.pm (revision 606514) +++ lib/Mail/SpamAssassin/BayesStore/DBM.pm (working copy) @@ -279,7 +279,11 @@ my $name = $path.'_'.$dbname; my $db_var = 'db_'.$dbname; dbg("bayes: tie-ing to DB file R/W $name"); - tie %{$self->{$db_var}},$self->DBM_MODULE,$name, O_RDWR|O_CREAT, + + ($self->DBM_MODULE eq 'DB_File') and + Mail::SpamAssassin::Util::avoid_db_file_locking_bug ($name); + + tie %{$self->{$db_var}},$self->DBM_MODULE, $name, O_RDWR|O_CREAT, (oct($main->{conf}->{bayes_file_mode}) & 0666) or goto failed_to_tie; } Index: lib/Mail/SpamAssassin/DBBasedAddrList.pm =================================================================== --- lib/Mail/SpamAssassin/DBBasedAddrList.pm (revision 606514) +++ lib/Mail/SpamAssassin/DBBasedAddrList.pm (working copy) @@ -82,15 +82,19 @@ dbg("auto-whitelist: tie-ing to DB file of type $dbm_module $mod1 in $path"); + ($self->{is_locked} && $dbm_module eq 'DB_File') and + Mail::SpamAssassin::Util::avoid_db_file_locking_bug ($path); + if (! tie %{ $self->{accum} }, $dbm_module, $path, $mod2, - oct($main->{conf}->{auto_whitelist_file_mode}) ) { - my $err = $!; # might get overwritten later - if ($self->{is_locked}) { - $self->{main}->{locker}->safe_unlock($self->{locked_file}); - $self->{is_locked} = 0; - } - die "auto-whitelist: cannot open auto_whitelist_path $path: $err\n"; + oct($main->{conf}->{auto_whitelist_file_mode}) ) + { + my $err = $!; # might get overwritten later + if ($self->{is_locked}) { + $self->{main}->{locker}->safe_unlock($self->{locked_file}); + $self->{is_locked} = 0; } + die "auto-whitelist: cannot open auto_whitelist_path $path: $err\n"; + } } bless ($self, $class); Index: lib/Mail/SpamAssassin/Util.pm =================================================================== --- lib/Mail/SpamAssassin/Util.pm (revision 606514) +++ lib/Mail/SpamAssassin/Util.pm (working copy) @@ -57,6 +57,7 @@ use Config; use File::Spec; +use File::Basename; use Time::Local; use Sys::Hostname (); # don't import hostname() into this namespace! use Fcntl; @@ -1551,6 +1552,32 @@ ########################################################################### +# bug 5612: work around for bugs in Berkeley db 4.2 +# +# on 4.2 having the __db.[DBNAME] file will cause an loop that will never finish +# on 4.3+ the loop will timeout after 301 open attempts, but we will still +# be unable to open the database. This workaround solves both problems. +# +sub avoid_db_file_locking_bug { + my ($path) = @_; + + my $db_tmpfile = untaint_file_path(File::Spec->catfile(dirname($path), + '__db.'.basename($path))); + + # delete "__db.[DBNAME]" and "__db.[DBNAME].*" + foreach my $tfile ($db_tmpfile, <$db_tmpfile.*>) { + my $file = untaint_file_path($tfile); + next unless (-e $file); + + dbg("Berkeley DB bug work-around: cleaning tmp file $file"); + if (!unlink($file)) { + die "cannot remove Berkeley DB tmp file $file: $!\n"; + } + } +} + +########################################################################### + 1; =back