http://qs321.pair.com?node_id=483774


in reply to Storable and passed filehandles

The flock is only advisory - it is not guarranteed.

The best way to coordinate your programs on the same server is to use a proper interprocess locker, such as IPC::Semaphore (I assume that you are working on Unix systems), create a public lock, and have all the processes that want to read the file to obtain that lock before accessing the file.

If the file you are trying to access is on the network, then use a network locking mechanism, such as, say, IPC::Locker.

Replies are listed 'Best First'.
Re^2: Storable and passed filehandles
by blahblah (Friar) on Aug 15, 2005 at 21:19 UTC
    I am working on a unix system (FreeBSD), and thanks for the semaphore pointer (further explained here).
    I guess I'm just surprised that the above doesn't work. As I test and test and re-test I am completely duped that even this simple code doesn't work...

    #!/usr/bin/perl -w # start with no existing giant.db file use strict; use Fcntl qw(:DEFAULT :flock); use Storable qw(store_fd fd_retrieve retrieve); use Data::Dumper; $Data::Dumper::Deepcopy=1; $Data::Dumper::Purity=1; $Data::Dumper::Sortkeys=1; my %data = ( 1 => 'FEE', 2 => 'FYE', 3 => 'FOH', 4 => 'FUM', ); sysopen(*DB, "giant.db", O_RDWR|O_CREAT, 0666) or die("sysopen: $!\n") +; flock(*DB, LOCK_EX) or die("flock: $!\n"); my $hashref = fd_retrieve(*DB); # modify the data, do work, etc.. $hashref->{$_} = $data{$_} for sort keys %data; store_fd($hashref, *DB) or die("store_fd: $!\n"); truncate(*DB, tell(*DB)); close(*DB);

    I'm totally spent and frustrated. Does anyone have any idea why this doesn't work? I must be missing something. I'm just trying to block access to a file while I change it. The above SHOULD work, shouldn't it?....shouldn't it?....please?

    Thanks
      Try the flock implemented by Storable first...
      #!/opt/kalm/bin/perl -w use strict; use Storable qw(lock_store lock_retrieve); use Data::Dumper; $Data::Dumper::Deepcopy=1; $Data::Dumper::Purity=1; $Data::Dumper::Sortkeys=1; my %data = ( 1 => 'FEE', 2 => 'FYE', 3 => 'FOH', 4 => 'FUM', ); my $file = 'test.dat'; lock_store \%data, $file; my $hashref = lock_retrieve $file; print Dumper($hashref);
        I had tried that, but it doesn't do what I need. It only locks the file during the actual read and write. It doesn't hold the lock to prevent other processes from changing the data while I do my thing.

        When we commit our changes we blast over each others changes.

      In general, passing in \*DB is better than just *DB.

      Looking at the docs for Storable I see both ways documented.

      However, when reading the source, it looks like using just *DB would get you a fatal "not a ref" thrown, though I don't see you describe the failure beyong "doesn't work" (the universal useless problem description) in your node.

      - tye        

        Doh. Sorry 'bout that. The error I'm getting is:

        Magic number checking on storable file failed at ../../lib/Storable.pm (autosplit into ../../lib/auto/Storable/fd_retrieve.al) line 341, at ./483993.pl line 16

        using the second, much smaller code snippet I posted.