Bug#417999: perl: GDBM tied hash weirdness - deletion in 'each' loop does nothing

Dominic Hargreaves dom at earth.li
Fri Dec 15 12:02:40 UTC 2017


Control: tags -1 + fixed-upstream

On Mon, Apr 01, 2013 at 10:27:24PM +0100, Dominic Hargreaves wrote:
> tags 417999 +confirmed
> retitle 417999 GDBM tied hash weirdness; deletion ends 'each' loop
> thanks
> 
> On Thu, Apr 05, 2007 at 09:53:38PM -0400, Ian Zimmerman wrote:
> > Try the following pearl:
> > 
> > ## begin test script
> > 
> > #! /usr/bin/perl
> > 
> > use GDBM_File;
> > 
> > %iddb = ();
> > tie %iddb, 'GDBM_File', './weird', &GDBM_WRCREAT|&GDBM_NOLOCK, 0600;
> > for (1..200) { $iddb{"foo$_"} = $_; }
> > 
> > print "Before deletion:\n\n";
> > while (my ($k, $v) = each %iddb) { print "$k:$v\n"; }
> > 
> > while (my ($k, $v) = each %iddb) { delete $iddb{$k} if $v > 150 ; }
> > print "\n\nAfter deletion:\n\n";
> > while (my ($k, $v) = each %iddb) { print "$k:$v\n"; }
> > 
> > untie %iddb;
> > 
> > ## end test script
> 
> Not quite nothing; the first deletion in the second loop does happen, but
> the loop is then broken out of. In other words, 'each' is returning undef
> immediately after the successful deletion. This isn't what either the
> perldoc for 'each' or 'delete' suggests should happen, and the 'GDBM_File'
> manpage doesn't have anything useful either. It does look like a bug
> (since perldoc -feach explicitly says you can delete the current hash
> member from within an interation).
> 
> You can see this a bit more clearly with the following:
> 
> #! /usr/bin/perl
> 
> use GDBM_File;
> use warnings;
> 
> %iddb = ();
> tie %iddb, 'GDBM_File', './weird', &GDBM_WRCREAT|&GDBM_NOLOCK, 0600;
> 
> for (1..20) { $iddb{"$_"} = $_; }
> 
> print "Before deletion:\n\n";
> while (my ($k, $v) = each %iddb) { print "$k:$v\n"; }
> 
> while (1) {
>     sleep 1;
>     $k = each %iddb;
>     print "k is $k\n";
>     delete $iddb{$k} if $k > 15;
> }
> 
> The same behaviour was described way back in 1997, but at the time
> the documentation didn't allow for deletion of the current iterator,
> even though it worked in the simple case (no tie):
> 
> http://diswww.mit.edu/bloom-picayune.mit.edu/perl/7564
> 
> (search for GDBM)
> 
> It looks like a genuine bug, one way or another, and I'm probably going
> to forward it upstream, better late than never.

Upstream has explained the situation here:

https://rt.perl.org/Ticket/Display.html?id=117449

In brief, this is a limitation of GDBM and can't realistically be fixed.
This limitation will be fixed in a future release of perl.

Cheers,
Dominic.




More information about the Perl-maintainers mailing list