Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GDBM tied hash weirdness; deletion ends 'each' loop #12894

Closed
p5pRT opened this issue Apr 2, 2013 · 4 comments
Closed

GDBM tied hash weirdness; deletion ends 'each' loop #12894

p5pRT opened this issue Apr 2, 2013 · 4 comments

Comments

@p5pRT
Copy link
Collaborator

@p5pRT p5pRT commented Apr 2, 2013

Migrated from rt.perl.org#117449 (status was 'resolved')

Searchable as RT117449$

@p5pRT
Copy link
Collaborator Author

@p5pRT p5pRT commented Apr 2, 2013

From @jmdh

Created by @jmdh

The following bug was reported in Debian​:
<http​://bugs.debian.org/cgi-bin/bugreport.cgi?bug=417999>

The test program which follows demonstrates that, contrary to all
available documentation (perlfunc and the minimal GDBM_File doc)
the current entry cannot be deleted from a GDBM tied hash​:

#! /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;
}

Immediately after the delete, each apparently returns undef.

This behaviour appears to have been the case since roughly forever[1]
but it does go against documentated behaviour, so does appear to be
a genuine bug as far as I can see.

From perlfunc​:

  After "each" has returned all entries from the hash or array,
  the next call to "each" returns the empty list in list context
  and "undef" in scalar context; the next call following that one
  restarts iteration. Each hash or array has its own internal
  iterator, accessed by "each", "keys", and "values". The
  iterator is implicitly reset when "each" has reached the end as
  just described; it can be explicitly reset by calling "keys" or
  "values" on the hash or array. If you add or delete a hash's
  elements while iterating over it, entries may be skipped or
  duplicated--so don't do that. Exception​: In the current
  implementation, it is always safe to delete the item most
  recently returned by "each()", so the following code works
  properly​:

  while (($key, $value) = each %hash) {
  print $key, "\n";
  delete $hash{$key}; # This is safe
  }

[1] <http​://diswww.mit.edu/bloom-picayune.mit.edu/perl/7564>

Perl Info

Flags:
    category=library
    severity=low
    module=GDBM_File

Site configuration information for perl 5.17.10:

Configured by dom at Sun Mar 31 23:53:26 BST 2013.

Summary of my perl5 (revision 5 version 17 subversion 10) configuration:
   
  Platform:
    osname=linux, osvers=3.2.0-4-686-pae, archname=i686-linux
    uname='linux callisto 3.2.0-4-686-pae #1 smp debian 3.2.39-2 i686 gnulinux '
    config_args='-de -Dprefix=/home/dom/perl5/perlbrew/perls/perl-5.17.10 -Dusedevel'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.7.2', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib/i386-linux-gnu /lib/../lib /usr/lib/i386-linux-gnu /usr/lib/../lib /lib /usr/lib
    libs=-lnsl -ldl -lm -lcrypt -lutil -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.13'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector'

Locally applied patches:
    


@INC for perl 5.17.10:
    /home/dom/perl5/perlbrew/perls/perl-5.17.10/lib/site_perl/5.17.10/i686-linux
    /home/dom/perl5/perlbrew/perls/perl-5.17.10/lib/site_perl/5.17.10
    /home/dom/perl5/perlbrew/perls/perl-5.17.10/lib/5.17.10/i686-linux
    /home/dom/perl5/perlbrew/perls/perl-5.17.10/lib/5.17.10
    .


Environment for perl 5.17.10:
    HOME=/home/dom
    LANG=en_GB.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/dom/perl5/perlbrew/bin:/home/dom/perl5/perlbrew/perls/perl-5.17.10/bin:~/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
    PERLBREW_MANPATH=/home/dom/perl5/perlbrew/perls/perl-5.17.10/man
    PERLBREW_PATH=/home/dom/perl5/perlbrew/bin:/home/dom/perl5/perlbrew/perls/perl-5.17.10/bin
    PERLBREW_PERL=perl-5.17.10
    PERLBREW_ROOT=/home/dom/perl5/perlbrew
    PERLBREW_SKIP_INIT=1
    PERLBREW_VERSION=0.43
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Collaborator Author

@p5pRT p5pRT commented Dec 15, 2017

From zefram@fysh.org

This weirdness arises because deleting from a gdbm hash can reorganise
the hash. Unlike Perl's own hashes, gdbm has no exception for deleting
the current entry. This is explained at some length in the gdbm
documentation. It is therefore impossible to make such deletion work as
desired, without making GDBM_File a far thicker layer over libgdbm than
it is clearly intended to be. I have put a note about this issue in the
GDBM_File documention in commit 3752113.

-zefram

@p5pRT
Copy link
Collaborator Author

@p5pRT p5pRT commented Dec 15, 2017

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Collaborator Author

@p5pRT p5pRT commented Dec 15, 2017

@iabyn - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant
You can’t perform that action at this time.