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