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.