Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

hi all,

i wonder whether some of you encountered the same error and can point me to what's going wrong.

i'm trying to use a gdbm file for storage of large and complex data structures. funny enough, writing them doesn't make any problem, but when i'm trying to read the previously stored data, GDBM_File.pm dies without giving me a reason. When i ran the code step by step under perldb, at one time there was an error message "Bad file descriptor" - but that was not reproducable. here's the code:

package Foo::DBM; use strict; use vars qw /$VERSION @ISA/; $VERSION = 1.0; use Exporter; @ISA = qw/Exporter/; use GDBM_File; use Storable qw/freeze thaw/; sub new { my ($class, $path, $type, $key) = @_; my $self = { PATH => $path, TYPE => $type, KEY => $key, RECORD => { +} }; bless $self, $class; $self->read if $key; $self; } sub read { my $self = shift; die "Can't read without knowing what" unless $self->{KEY}; my $filename = "$self->{PATH}/$self->{TYPE}"; $filename =~ s/\/\//\//g; my %file; tie %file, 'GDBM_File', $filename, GDBM_READER || die $!; my $rec = $file{$self->{KEY}}; $self->{RECORD} = thaw $rec; untie %file; 1; } sub save { my $self = shift; die "Can't write without knowing where" unless $self->{KEY}; my $filename = "$self->{PATH}/$self->{TYPE}"; $filename =~ s/\/\//\//g; my %file; tie %file, 'GDBM_File', $filename, GDBM_WRCREAT, 0640 || die $!; my $rec = freeze $self->{RECORD}; $file{$self->{KEY}} = $rec; untie %file; 1; } 1;

the line producing the code is in sub read{} and tunes:tie %file, 'GDBM_File', $filename, GDBM_READER || die $!;

i have no idea at all how to solve this problem, so any clues will be appreciated. many thx in advance.

Janitored: <readmore> tags added by davido.

Replies are listed 'Best First'.
Re: GDBM_File dies without telling why
by graff (Chancellor) on Jul 03, 2005 at 04:25 UTC
    When you stepped through with the debugger, did you confirm that the call to Foo::DBM->new() provided correct values for the PATH and TYPE args? Did you check the value of $filename before using tie? And if that value was as expected, did you check that the file(s) actually exist?

    Does the failure in the read() call happen in the same calling program that used the save() call? (I trust you are making sure to save something to the file before trying to read it...)

    Sorry, no answers yet, just questions. That's because I don't see anything wrong with the code as it stands. Maybe I would add parens around the args in the tie call, and use "or die" instead of "|| die", just to make sure there isn't any confusion about precedence (e.g. just in case the GDBM_READER constant is defined as "0", which means that the last arg to tie would be parsed as "GDBM_READER || die", which would evaluate to the return value of the "die" call -- not what you want).

    Update: having seen the first reply (posted while I was writing this one), it's plausible that adding the extra permission arg (which would always evaluate to true) before the "|| die" works because it's another way of decoupling "GDBM_READER" and "|| die". If this is the case, that "die" call might never get invoked as a result of a failed return from tie. I'd still suggest using parens and "or die".

    Another update: sure, you can just add parens around the tie args, or just switch from "|| die" to "or die" -- either step by itself would be sufficient. But you need to do at least one of them if you want that "die" trap to really work as intended.

Re: GDBM_File dies without telling why
by Anonymous Monk on Jul 03, 2005 at 04:19 UTC
    ok, i found it! :)

    GDBM_File::TIEHASH obviously needs the file permissions, even when being called for reading only. this ought to be considered a bug, see http://www.csa.iisc.ernet.in/old-website/Department_Resources/Hypertext/gdbm/gdbm_4.html#SEC4