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

FileCache only works in "main" package #7693

Closed
p5pRT opened this issue Dec 7, 2004 · 21 comments
Closed

FileCache only works in "main" package #7693

p5pRT opened this issue Dec 7, 2004 · 21 comments

Comments

@p5pRT
Copy link

p5pRT commented Dec 7, 2004

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

Searchable as RT32949$

@p5pRT
Copy link
Author

p5pRT commented Dec 7, 2004

From @kaibolay

This is a bug report for perl from kai@​bolay.de,
generated with the help of perlbug 1.35 running under perl v5.8.5.

----------------------------------------------------------------- I
expected to be able to use the FileCache module from any package
module I want. Obviously it doesn't work (see below). I'm not enough
of an expert with typeglobs and package scoping to fix this myself.

As a workaround I temporarily switch to the "main" package when using
FileCache. That works but seems like a bad hack.

$ cat FileCacheBug.pl
#!/usr/bin/perl -w

use strict;
use FileCache;

eval {
  no strict "refs";
  my $filename = "testfile.$$.tmp";
  cacheout($filename);
  print $filename "data\n";
  unlink($filename);
};
if (!$@​) {
  print "using FileCache in 'main' package works\n";
} else {
  print "using FileCache in 'main' package fails​: $@​";
}

eval {
  package anything;

  no strict "refs";
  my $filename = "testfile.$$.tmp";
  cacheout($filename);
  print $filename "data\n";
  unlink($filename);
};

if (!$@​) {
  print "using FileCache in any package works\n";
} else {
  print "using FileCache in any package fails​: $@​";
}

eval {
  package anything;

  no strict "refs";
  my $filename = "testfile.$$.tmp";
  FileCache​::cacheout($filename);
  print $filename "data\n";
  unlink($filename);
};

if (!$@​) {
  print "using FileCache in any package works?!\n";
} else {
  print "using FileCache in any package fails​: $@​";
}

$ ./FileCacheBug.pl
using FileCache in 'main' package works
using FileCache in any package fails​: Undefined subroutine &anything​::cacheout called at ./FileCacheBug.pl line 24.
print() on unopened filehandle testfile.18245.tmp at ./FileCacheBug.pl line 41.
using FileCache in any package works?!



Flags​:
  category=library
  severity=medium


This perlbug was built using Perl v5.8.5 in the Red Hat build system.
It is being executed now by Perl v5.8.5 - Tue Oct 12 12​:44​:18 EDT 2004.

Site configuration information for perl v5.8.5​:

Configured by Red Hat, Inc. at Tue Oct 12 12​:44​:18 EDT 2004.

Summary of my perl5 (revision 5 version 8 subversion 5) configuration​:
  Platform​:
  osname=linux, osvers=2.4.21-14.elsmp, archname=i386-linux-thread-multi
  uname='linux tweety.build.redhat.com 2.4.21-14.elsmp #1 smp wed apr 14 18​:55​:47 edt 2004 i686 i686 i386 gnulinux '
  config_args='-des -Doptimize=-O2 -g -pipe -m32 -march=i386 -mtune=pentium4 -Dversion=5.8.5 -Dmyhostname=localhost -Dperladmin=root@​localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr -Dinc_version_list=5.8.4 5.8.3 5.8.2 5.8.1 5.8.0'
  hint=recommended, useposix=true, d_sigaction=define
  usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
  useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
  use64bitint=undef use64bitall=undef uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm',
  optimize='-O2 -g -pipe -m32 -march=i386 -mtune=pentium4',
  cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -pipe -I/usr/local/include -I/usr/include/gdbm'
  ccversion='', gccversion='3.4.2 20041006 (Red Hat 3.4.2-5)', 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='gcc', ldflags =' -L/usr/local/lib'
  libpth=/usr/local/lib /lib /usr/lib
  libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc
  perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
  libc=/lib/libc-2.3.3.so, so=so, useshrplib=true, libperl=libperl.so
  gnulibc_version='2.3.3'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/usr/lib/perl5/5.8.5/i386-linux-thread-multi/CORE'
  cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'

Locally applied patches​:
 


@​INC for perl v5.8.5​:
  /usr/lib/perl5/5.8.5/i386-linux-thread-multi
  /usr/lib/perl5/5.8.5
  /usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi
  /usr/lib/perl5/site_perl/5.8.4/i386-linux-thread-multi
  /usr/lib/perl5/site_perl/5.8.3/i386-linux-thread-multi
  /usr/lib/perl5/site_perl/5.8.2/i386-linux-thread-multi
  /usr/lib/perl5/site_perl/5.8.1/i386-linux-thread-multi
  /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi
  /usr/lib/perl5/site_perl/5.8.5
  /usr/lib/perl5/site_perl/5.8.4
  /usr/lib/perl5/site_perl/5.8.3
  /usr/lib/perl5/site_perl/5.8.2
  /usr/lib/perl5/site_perl/5.8.1
  /usr/lib/perl5/site_perl/5.8.0
  /usr/lib/perl5/site_perl
  /usr/lib/perl5/vendor_perl/5.8.5/i386-linux-thread-multi
  /usr/lib/perl5/vendor_perl/5.8.4/i386-linux-thread-multi
  /usr/lib/perl5/vendor_perl/5.8.3/i386-linux-thread-multi
  /usr/lib/perl5/vendor_perl/5.8.2/i386-linux-thread-multi
  /usr/lib/perl5/vendor_perl/5.8.1/i386-linux-thread-multi
  /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi
  /usr/lib/perl5/vendor_perl/5.8.5
  /usr/lib/perl5/vendor_perl/5.8.4
  /usr/lib/perl5/vendor_perl/5.8.3
  /usr/lib/perl5/vendor_perl/5.8.2
  /usr/lib/perl5/vendor_perl/5.8.1
  /usr/lib/perl5/vendor_perl/5.8.0
  /usr/lib/perl5/vendor_perl
  .


Environment for perl v5.8.5​:
  HOME=/home/kbolay
  LANG=en_US
  LANGUAGE (unset)
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)
  PATH=/usr/kerberos/bin​:/usr/local/bin​:/usr/bin​:/bin​:/usr/X11R6/bin​:/sbin​:/usr/local/sbin​:/home/kbolay/bin​:/sbin​:/usr/local/sbin​:/sbin​:/usr/local/sbin​:/sbin​:/usr/local/sbin​:/sbin​:/usr/local/sbin
  PERL_BADLANG (unset)
  SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Dec 8, 2004

From @schwern

On Tue, Dec 07, 2004 at 10​:45​:16PM -0000, kai @​ bolay. de wrote​:

expected to be able to use the FileCache module from any package
module I want. Obviously it doesn't work (see below). I'm not enough
of an expert with typeglobs and package scoping to fix this myself.

As a workaround I temporarily switch to the "main" package when using
FileCache. That works but seems like a bad hack.

Unless I'm misunderstanding, this is not a bug in FileCache. This is how
most modules which export functions work.

  use Text​::Soundex;
  print soundex("foo");

  package Foo;
  print soundex("bar")'

F000
Undefined subroutine &Foo​::soundex called at -e line 1.

Module will typically only export their functions into the current package.
This is to prevent "namespace pollution", modules and functions in one
package showing up in another. This is basic encapsulation.

If you want to use FileCache or any module's functions in a package you
must first use that module *in that package*. It is fine to use a module
more than once in the same program.

eval {
package anything;

Add a "use File​::Cache;" here and you're good.

no strict "refs";
my $filename = "testfile\.$$\.tmp";
cacheout\($filename\);
print $filename "data\\n";
unlink\($filename\);

};

if (!$@​) {
print "using FileCache in any package works\n";
} else {
print "using FileCache in any package fails​: $@​";
}

--
Michael G Schwern schwern@​pobox.com http​://www.pobox.com/~schwern/
What's a classy place like this doing around a low-life like you?

@p5pRT
Copy link
Author

p5pRT commented Dec 8, 2004

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

@p5pRT
Copy link
Author

p5pRT commented Dec 8, 2004

From @tamias

On Wed, Dec 08, 2004 at 12​:06​:29AM -0500, Michael G Schwern wrote​:

eval {
package anything;

Add a "use File​::Cache;" here and you're good.

I was going to make the same suggestion, but I tried it, and it didn't
work. It turns out that FileCache doesn't have a package statement, so its
subroutines are always in the main package and its import method is never
called. The original submitter is correct that this is a bug.

Ronald

@p5pRT
Copy link
Author

p5pRT commented Dec 8, 2004

From @schwern

On Wed, Dec 08, 2004 at 12​:38​:33AM -0500, Ronald J Kimball wrote​:

On Wed, Dec 08, 2004 at 12​:06​:29AM -0500, Michael G Schwern wrote​:

eval {
package anything;

Add a "use File​::Cache;" here and you're good.

I was going to make the same suggestion, but I tried it, and it didn't
work. It turns out that FileCache doesn't have a package statement, so its

Its line 1.

The problem appears to be that its exporting to caller(1) not caller(0).
Thus one level too far up the stack. It should probably just be using
Exporter.

--
Michael G Schwern schwern@​pobox.com http​://www.pobox.com/~schwern/
1 4m 4 31134 h4X0R \/\/H1 15 /\/\1 5cR33N B100??!?!?!?

@p5pRT
Copy link
Author

p5pRT commented Dec 8, 2004

From kane@xs4all.net

On Dec 8, 2004, at 7​:09 AM, Michael G Schwern wrote​:

Its line 1.

The problem appears to be that its exporting to caller(1) not
caller(0).
Thus one level too far up the stack. It should probably just be using
Exporter.

I'll send a patch for use of Exporter + tests along this afternoon
(announcing, just to make sure there's no duplicate effort)

--
  Jos Boumans

  'Real programmers use "cat > a.out"'

  CPANPLUS http​://cpanplus.sf.net

@p5pRT
Copy link
Author

p5pRT commented Dec 8, 2004

From kane@xs4all.net

On Dec 8, 2004, at 9​:57 AM, Jos I. Boumans wrote​:

On Dec 8, 2004, at 7​:09 AM, Michael G Schwern wrote​:

Its line 1.

The problem appears to be that its exporting to caller(1) not
caller(0).
Thus one level too far up the stack. It should probably just be using
Exporter.

I'll send a patch for use of Exporter + tests along this afternoon
(announcing, just to make sure there's no duplicate effort)

Patch attached to make FileCache use Exporter, plus a new test file
(including MANIFEST patch) to test
for this behaviour. Tests all seem to work fine, ran 'make test' on the
latest blead just to be sure​:

lib/FileCache/t/01open....................ok
lib/FileCache/t/02maxopen.................ok
lib/FileCache/t/03append..................ok
lib/FileCache/t/04twoarg..................ok
lib/FileCache/t/05override................ok
lib/FileCache/t/06export..................ok
[...]
All tests successful.
u=3.92 s=3.42 cu=303.16 cs=63.87 scripts=867 tests=97594

--
  Jos Boumans

  From kid's Superman costume for Halloween (stitched into the cape's
tag) -- "Warning​: Use of This Device Does Not Enable
  Wearer To Fly."

  CPANPLUS http​://cpanplus.sf.net

@p5pRT
Copy link
Author

p5pRT commented Dec 8, 2004

From kane@xs4all.net

filecache-exporter-[#32949].patch
--- MANIFEST.org        Wed Dec  8 11:02:20 2004
+++ MANIFEST    Wed Dec  8 10:37:27 2004
@@ -1345,6 +1345,7 @@
 lib/FileCache/t/03append.t     See if FileCache works
 lib/FileCache/t/04twoarg.t     See if FileCache works
 lib/FileCache/t/05override.t   See if FileCache works
+lib/FileCache/t/06export.t     See if FileCache exporting works
 lib/File/CheckTree.pm          Perl module supporting wholesale file mode validation
 lib/File/CheckTree.t           See if File::CheckTree works
 lib/File/Compare.pm            Emulation of cmp command
--- lib/FileCache.pm.org        Wed Dec  8 10:10:12 2004
+++ lib/FileCache.pm    Wed Dec  8 14:20:33 2004
@@ -84,15 +84,27 @@
 # These are not C<my> for legacy reasons.
 # Previous versions requested the user set $cacheout_maxopen by hand.
 # Some authors fiddled with %saw to overcome the clobber on initial open.
-use vars qw(%saw $cacheout_maxopen);
+use vars qw(%saw $cacheout_maxopen @EXPORT);
 my %isopen;
 my $cacheout_seq = 0;
 
 sub import {
     my ($pkg,%args) = @_;
-    $pkg = caller(1);
-    *{$pkg.'::cacheout'} = \&cacheout;
-    *{$pkg.'::close'}    = \&cacheout_close;
+
+    # Not using Exporter is naughty.
+    # Also, using caller(1) is just wrong.
+    #$pkg = caller(1);
+    #*{$pkg.'::cacheout'} = \&cacheout;
+    #*{$pkg.'::close'}    = \&cacheout_close;
+
+    # Use Exporter. %args are for us, not Exporter.
+    # Make sure to up export_to_level, or we will import into ourselves,
+    # rather than our calling package;
+    use base 'Exporter';
+    @EXPORT = qw[cacheout cacheout_close];
+
+    __PACKAGE__->export_to_level(1);
+    Exporter::import( $pkg );
 
     # Truth is okay here because setting maxopen to 0 would be bad
     return $cacheout_maxopen = $args{maxopen} if $args{maxopen};

diff -u /dev/null lib/FileCache/t/06export.t
--- /dev/null   Wed Dec  8 11:05:55 2004
+++ lib/FileCache/t/06export.t  Wed Dec  8 11:05:39 2004
@@ -0,0 +1,62 @@
+#!./perl
+BEGIN {
+    chdir 't' if -d 't';
+
+    #For tests within the perl distribution
+    @INC = '../lib' if -d '../lib';
+    END;
+
+    # Functions exported by FileCache;
+    @funcs  = qw[cacheout cacheout_close];
+    $i      = 0;
+    
+    # number of tests
+    print "1..8\n";
+}
+
+# Test 6: Test that exporting both works to package main and
+# other packages. Now using Exporter.
+
+# First, we shouldn't be able to have these in our namespace
+# Add them to BEGIN so the later 'use' doesn't influence this
+# test
+BEGIN {   
+    for my $f (@funcs) {
+        ++$i;
+        print 'not ' if __PACKAGE__->can($f);
+        print "ok $i\n"; 
+    }
+}
+
+# With an empty import list, we also shouldn't have them in
+# our namespace.
+# Add them to BEGIN so the later 'use' doesn't influence this
+# test
+BEGIN {   
+    use FileCache ();
+    for my $f (@funcs) {
+        ++$i;
+        print 'not ' if __PACKAGE__->can($f);
+        print "ok $i\n"; 
+    }
+}
+
+
+# Now, we use FileCache in 'main'
+{   use FileCache;
+    for my $f (@funcs) {
+        ++$i;
+        print 'not ' if !__PACKAGE__->can($f);
+        print "ok $i\n"; 
+    }
+}
+
+# Now we use them in another package
+{   package X;
+    use FileCache;
+    for my $f (@main::funcs) {
+        ++$main::i;
+        print 'not ' if !__PACKAGE__->can($f);
+        print "ok $main::i\n"; 
+    }
+}

@p5pRT
Copy link
Author

p5pRT commented Dec 8, 2004

From @rgs

Jos I. Boumans wrote​:

On Dec 8, 2004, at 9​:57 AM, Jos I. Boumans wrote​:

On Dec 8, 2004, at 7​:09 AM, Michael G Schwern wrote​:

Its line 1.

The problem appears to be that its exporting to caller(1) not
caller(0).
Thus one level too far up the stack. It should probably just be using
Exporter.

I'll send a patch for use of Exporter + tests along this afternoon
(announcing, just to make sure there's no duplicate effort)

Patch attached to make FileCache use Exporter, plus a new test file
(including MANIFEST patch) to test
for this behaviour. Tests all seem to work fine, ran 'make test' on the
latest blead just to be sure​:

Thanks, applied as #23627.

@p5pRT
Copy link
Author

p5pRT commented Dec 8, 2004

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

@p5pRT
Copy link
Author

p5pRT commented Dec 8, 2004

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

@p5pRT
Copy link
Author

p5pRT commented Dec 8, 2004

From @kaibolay

Thanks for the quick response(s)!

Unfortunately the socond aspect of the bug is still there. I think it is
related to the use of caller(1) in cacheout_open()​:

# Open in their package.
sub cacheout_open {
  return open(*{caller(1) . '​::' . $_[1]}, $_[0], $_[1]) && $_[1];
}

I attached a patch to your 06export.t which tries to show the problem.
Stangely enough tests 8 and 11 fail. If I run the test under perl -d
then only test 11 fails, but test 8 works. Weird!

Here's the output when I run the patched test script with your patched
FileCache.pm​:

1..11
ok 1
ok 2
ok 3
ok 4
Use of uninitialized value in subtraction (-) at FileCache.pm line 162.
Use of uninitialized value in division (/) at FileCache.pm line 165.
Use of uninitialized value in splice at FileCache.pm line 165.
ok 5
ok 6
ok 7
print() on closed filehandle foo.23522.1102539750 at 06export.t line 65.
Use of uninitialized value in string ne at 06export.t line 69.
not ok 8
ok 9
ok 10
print() on unopened filehandle foo.23522.1102539750 at 06export.t line 84.
close() on unopened filehandle foo.23522.1102539750 at 06export.t line 84.
Use of uninitialized value in string ne at 06export.t line 88.
not ok 11

I guess the problems on line 162 and 165 in FileCache.pm should also be
fixed.

Thanks so much!

@p5pRT
Copy link
Author

p5pRT commented Dec 8, 2004

From @kaibolay

bug.patch
*** 06export.t.org	2004-12-08 15:59:10.005377914 -0500
--- 06export.t	2004-12-08 15:56:34.527858529 -0500
***************
*** 1,4 ****
! #!./perl
  BEGIN {
      chdir 't' if -d 't';
  
--- 1,4 ----
! #!./perl -w
  BEGIN {
      chdir 't' if -d 't';
  
*************** BEGIN {
*** 8,17 ****
  
      # Functions exported by FileCache;
      @funcs  = qw[cacheout cacheout_close];
      $i      = 0;
      
      # number of tests
!     print "1..8\n";
  }
  
  # Test 6: Test that exporting both works to package main and
--- 8,18 ----
  
      # Functions exported by FileCache;
      @funcs  = qw[cacheout cacheout_close];
+ 
      $i      = 0;
  
      # number of tests
!     print "1..11\n";
  }
  
  # Test 6: Test that exporting both works to package main and
*************** BEGIN {   
*** 39,44 ****
--- 40,54 ----
          print 'not ' if __PACKAGE__->can($f);
          print "ok $i\n"; 
      }
+ 
+     ++$i;
+     my $file = "foo.$$.".time();
+     FileCache::cacheout $file;  print $file "content"; close($file);
+     my $content;
+     if (open($file, "<", $file)) {local $/; $content=<$file>; close ($file);}
+     unlink($file);
+     print "not " if ($content ne "content");
+     print "ok $i\n";
  }
  
  
*************** BEGIN {   
*** 49,54 ****
--- 59,73 ----
          print 'not ' if !__PACKAGE__->can($f);
          print "ok $i\n"; 
      }
+ 
+     ++$i;
+     my $file = "foo.$$.".time();
+     cacheout $file;  print $file "content"; close($file);
+     my $content;
+     if (open($file, "<", $file)) {local $/; $content=<$file>; close ($file);}
+     unlink($file);
+     print "not " if ($content ne "content");
+     print "ok $i\n";
  }
  
  # Now we use them in another package
*************** BEGIN {   
*** 59,62 ****
--- 78,90 ----
          print 'not ' if !__PACKAGE__->can($f);
          print "ok $main::i\n"; 
      }
+ 
+     ++$main::i;
+     my $file = "foo.$$.".time();
+     cacheout $file;  print $file "content"; close($file);
+     my $content;
+     if (open($file, "<", $file)) {local $/; $content=<$file>; close ($file);}
+     unlink($file);
+     print "not " if ($content ne "content");
+     print "ok $main::i\n";
  }

@p5pRT
Copy link
Author

p5pRT commented Dec 11, 2004

From @schwern

[kbolay - Wed Dec 08 13​:23​:16 2004]​:

ok 4
Use of uninitialized value in subtraction (-) at FileCache.pm line 162.
Use of uninitialized value in division (/) at FileCache.pm line 165.
Use of uninitialized value in splice at FileCache.pm line 165.

This much at least is because FileCache​::import has not yet been called
to initialize $cacheout_maxopen. This is a minor problem in the test
exasperating some poorly thought out code in FileCache.
FileCache​::import() contains initialization code. Unless its called
things go wrong.

When you do "use FileCache ()" import is not called so $cache_maxopen is
never initialized. Adding a default fixes this.

@p5pRT
Copy link
Author

p5pRT commented Dec 11, 2004

From @schwern

[kbolay - Wed Dec 08 13​:23​:16 2004]​:

ok 7
print() on closed filehandle foo.23522.1102539750 at 06export.t line 65.
Use of uninitialized value in string ne at 06export.t line 69.
not ok 8
ok 9
ok 10
print() on unopened filehandle foo.23522.1102539750 at 06export.t line 84.
close() on unopened filehandle foo.23522.1102539750 at 06export.t line 84.
Use of uninitialized value in string ne at 06export.t line 88.
not ok 11

The rest of this is because, I think, FileCache does not check to see if
the file in question has gone away.

In your test you do this.

cacheout $file;
unlink $file;
cacheout $file;

FileCache does not check to see if the file has gone away and try to
reopen it.

This is separate from the exporting problem.

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2004

From @kaibolay

Michael G Schwern via RT wrote​:

The rest of this is because, I think, FileCache does not check to see if
the file in question has gone away.

In your test you do this.

cacheout $file;
unlink $file;
cacheout $file;

I think you're misreading my test script. The second (and third)
cacheout() calls in my test-script are for a different $file variable.

What I do is​:

{
  package main;

  my $file = "filename";
  cacheout $file;
  print $file;
  unlink $file;
}

{
  package other;

  my $file = "filename";
  cacheout $file;
  print $file;
  unlink $file;
}

[...]

FileCache does not check to see if the file has gone away and try to
reopen it.

This is separate from the exporting problem.

I don't think so. I think the "print() on unopened filehandle" is caused
by some typeglob magic in cacheout_open()​:

sub cacheout_open {
  return open(*{caller(1) . '​::' . $_[1]}, $_[0], $_[1]) && $_[1];
}

Jos I. Boumans <kane@​xs4all.net> replaced similar uses of caller(1) in
import() with using the Exporter module.

I've updated my test script to use $file1, $file2, and $file3 as
variables instead of reusing $file. The result is the same​:

[kbolay@​dose FileCacheBug]$ cat ./06export.t
#!./perl -w
BEGIN {
  chdir 't' if -d 't';

  #For tests within the perl distribution
  @​INC = '../lib' if -d '../lib';
  END;

  # Functions exported by FileCache;
  @​funcs = qw[cacheout cacheout_close];

  $i = 0;

  # number of tests
  print "1..11\n";
}

# Test 6​: Test that exporting both works to package main and
# other packages. Now using Exporter.

# First, we shouldn't be able to have these in our namespace
# Add them to BEGIN so the later 'use' doesn't influence this
# test
BEGIN {
  for my $f (@​funcs) {
  ++$i;
  print 'not ' if __PACKAGE__->can($f);
  print "ok $i\n";
  }
}

# With an empty import list, we also shouldn't have them in
# our namespace.
# Add them to BEGIN so the later 'use' doesn't influence this
# test
BEGIN {
  use FileCache ();
  for my $f (@​funcs) {
  ++$i;
  print 'not ' if __PACKAGE__->can($f);
  print "ok $i\n";
  }

  ++$i;
  my $file1 = "foo.$$.".time();
  FileCache​::cacheout $file1; print $file1 "content"; close($file1);
  my $content;
  if (open($file1, "<", $file1)) {local $/; $content=<$file1>; close
($file1);}
  unlink($file1);
  print "not " if ($content ne "content");
  print "ok $i\n";
}

# Now, we use FileCache in 'main'
{ use FileCache;
  for my $f (@​funcs) {
  ++$i;
  print 'not ' if !__PACKAGE__->can($f);
  print "ok $i\n";
  }

  ++$i;
  my $file2 = "foo.$$.".time();
  cacheout $file2; print $file2 "content"; close($file2);
  my $content;
  if (open($file2, "<", $file2)) {local $/; $content=<$file2>; close
($file2);}
  unlink($file2);
  print "not " if ($content ne "content");
  print "ok $i\n";
}

# Now we use them in another package
{ package X;
  use FileCache;
  for my $f (@​main​::funcs) {
  ++$main​::i;
  print 'not ' if !__PACKAGE__->can($f);
  print "ok $main​::i\n";
  }

  ++$main​::i;
  my $file3 = "foo.$$.".time();
  cacheout $file3; print $file3 "content"; close($file3);
  my $content;
  if (open($file3, "<", $file3)) {local $/; $content=<$file3>; close
($file3);}
  unlink($file3);
  print "not " if ($content ne "content");
  print "ok $main​::i\n";
}

[kbolay@​dose FileCacheBug]$ perl ./06export.t
1..11
ok 1
ok 2
ok 3
ok 4
Use of uninitialized value in subtraction (-) at FileCache.pm line 162.
Use of uninitialized value in division (/) at FileCache.pm line 165.
Use of uninitialized value in splice at FileCache.pm line 165.
ok 5
ok 6
ok 7
print() on closed filehandle foo.8065.1102972970 at ./06export.t line 65.
Use of uninitialized value in string ne at ./06export.t line 69.
not ok 8
ok 9
ok 10
print() on unopened filehandle foo.8065.1102972970 at ./06export.t line 84.
close() on unopened filehandle foo.8065.1102972970 at ./06export.t line 84.
Use of uninitialized value in string ne at ./06export.t line 88.
not ok 11

@p5pRT
Copy link
Author

p5pRT commented Dec 13, 2004

From @kaibolay

Michael G Schwern via RT wrote​:

  > The rest of this is because, I think, FileCache does not check to see if
  > the file in question has gone away.
  >
  > In your test you do this.
  >
  > cacheout $file;
  > unlink $file;
  > cacheout $file;

I think you're misreading my test script. The second (and third)
cacheout() calls in my test-script are for a different $file variable.

What I do is​:

{
  package main;

  my $file = "filename";
  cacheout $file;
  print $file;
  unlink $file;
}

{
  package other;

  my $file = "filename";
  cacheout $file;
  print $file;
  unlink $file;
}

[...]

  > FileCache does not check to see if the file has gone away and try to
  > reopen it.
  >
  > This is separate from the exporting problem.
  >

I don't think so. I think the "print() on unopened filehandle" is caused
  by some typeglob magic in cacheout_open()​:

sub cacheout_open {
  return open(*{caller(1) . '​::' . $_[1]}, $_[0], $_[1]) && $_[1];
}

Jos I. Boumans <kane@​xs4all.net> replaced similar uses of caller(1) in
import() with using the Exporter module.

I've updated my test script to use $file1, $file2, and $file3 as
variables instead of reusing $file. The result is the same​:

[kbolay@​dose FileCacheBug]$ cat ./06export.t
#!./perl -w
BEGIN {
  chdir 't' if -d 't';

  #For tests within the perl distribution
  @​INC = '../lib' if -d '../lib';
  END;

  # Functions exported by FileCache;
  @​funcs = qw[cacheout cacheout_close];

  $i = 0;

  # number of tests
  print "1..11\n";
}

# Test 6​: Test that exporting both works to package main and
# other packages. Now using Exporter.

# First, we shouldn't be able to have these in our namespace
# Add them to BEGIN so the later 'use' doesn't influence this
# test
BEGIN {
  for my $f (@​funcs) {
  ++$i;
  print 'not ' if __PACKAGE__->can($f);
  print "ok $i\n";
  }
}

# With an empty import list, we also shouldn't have them in
# our namespace.
# Add them to BEGIN so the later 'use' doesn't influence this
# test
BEGIN {
  use FileCache ();
  for my $f (@​funcs) {
  ++$i;
  print 'not ' if __PACKAGE__->can($f);
  print "ok $i\n";
  }

  ++$i;
  my $file1 = "foo.$$.".time();
  FileCache​::cacheout $file1; print $file1 "content"; close($file1);
  my $content;
  if (open($file1, "<", $file1)) {local $/; $content=<$file1>; close
($file1);}
  unlink($file1);
  print "not " if ($content ne "content");
  print "ok $i\n";
}

# Now, we use FileCache in 'main'
{ use FileCache;
  for my $f (@​funcs) {
  ++$i;
  print 'not ' if !__PACKAGE__->can($f);
  print "ok $i\n";
  }

  ++$i;
  my $file2 = "foo.$$.".time();
  cacheout $file2; print $file2 "content"; close($file2);
  my $content;
  if (open($file2, "<", $file2)) {local $/; $content=<$file2>; close
($file2);}
  unlink($file2);
  print "not " if ($content ne "content");
  print "ok $i\n";
}

# Now we use them in another package
{ package X;
  use FileCache;
  for my $f (@​main​::funcs) {
  ++$main​::i;
  print 'not ' if !__PACKAGE__->can($f);
  print "ok $main​::i\n";
  }

  ++$main​::i;
  my $file3 = "foo.$$.".time();
  cacheout $file3; print $file3 "content"; close($file3);
  my $content;
  if (open($file3, "<", $file3)) {local $/; $content=<$file3>; close
($file3);}
  unlink($file3);
  print "not " if ($content ne "content");
  print "ok $main​::i\n";
}

[kbolay@​dose FileCacheBug]$ perl ./06export.t
1..11
ok 1
ok 2
ok 3
ok 4
Use of uninitialized value in subtraction (-) at FileCache.pm line 162.
Use of uninitialized value in division (/) at FileCache.pm line 165.
Use of uninitialized value in splice at FileCache.pm line 165.
ok 5
ok 6
ok 7
print() on closed filehandle foo.8065.1102972970 at ./06export.t line 65.
Use of uninitialized value in string ne at ./06export.t line 69.
not ok 8
ok 9
ok 10
print() on unopened filehandle foo.8065.1102972970 at ./06export.t line 84.
close() on unopened filehandle foo.8065.1102972970 at ./06export.t line 84.
Use of uninitialized value in string ne at ./06export.t line 88.
not ok 11

@p5pRT
Copy link
Author

p5pRT commented Dec 14, 2004

From @schwern

On Mon, Dec 13, 2004 at 04​:33​:17PM -0500, Kai Bolay wrote​:

The rest of this is because, I think, FileCache does not check to see if
the file in question has gone away.

In your test you do this.

cacheout $file;
unlink $file;
cacheout $file;

I think you're misreading my test script. The second (and third)
cacheout() calls in my test-script are for a different $file variable.

But they're both set to the same *filename*. Therefore, without diving too
deeply into FileCache's logic, it appears to be saying "Oh, I already have
this open. Here's the already open filehandle" without first checking if
the file was deleted between cacheout calls.

{
package main;

my $file = "filename";
cacheout $file;
print $file;
unlink $file;

}

{
package other;

my $file = "filename";
cacheout $file;
print $file;
unlink $file;

}

[...]

FileCache does not check to see if the file has gone away and try to
reopen it.

This is separate from the exporting problem.

I don't think so. I think the "print() on unopened filehandle" is caused
by some typeglob magic in cacheout_open()​:

While I'm not sure the use of caller(1) is correct, I believe that to be
an orthoganal issue.

sub cacheout_open {
return open(*{caller(1) . '​::' . $_[1]}, $_[0], $_[1]) && $_[1];
}

Jos I. Boumans <kane@​xs4all.net> replaced similar uses of caller(1) in
import() with using the Exporter module.

I've updated my test script to use $file1, $file2, and $file3 as
variables instead of reusing $file. The result is the same​:

Try using a different *filename*.

--
Michael G Schwern schwern@​pobox.com http​://www.pobox.com/~schwern/
I have this god-awful need to aquire useless crap!!!

@p5pRT
Copy link
Author

p5pRT commented Dec 15, 2004

From @schwern

On Wed, Dec 15, 2004 at 01​:54​:37AM -0500, Kai Bolay wrote​:

Ah. You're right! Sorry about getting confused. Maybe FileCache can be
improved to somehow "bind" to the variable, not the file name?

Wouldn't it be easier to get it to check first if the filehandle was
closed or the file disappeared and reopen it if so?

--
Michael G Schwern schwern@​pobox.com http​://www.pobox.com/~schwern/
Anti-cow device. Don't bother.
  http​://www.goats.com/archive/990323.html

@p5pRT
Copy link
Author

p5pRT commented Dec 15, 2004

From @kaibolay

Michael G Schwern wrote​:

  > On Mon, Dec 13, 2004 at 04​:33​:17PM -0500, Kai Bolay wrote​:
  >
  >> I think you're misreading my test script. The second (and third)
  >> cacheout() calls in my test-script are for a different $file variable.
  >
  > But they're both set to the same *filename*. Therefore, without
diving too
  > deeply into FileCache's logic, it appears to be saying "Oh, I
already have
  > this open. Here's the already open filehandle" without first
checking if
  > the file was deleted between cacheout calls.

Ah. You're right! Sorry about getting confused. Maybe FileCache can be
improved to somehow "bind" to the variable, not the file name?

  >> I don't think so. I think the "print() on unopened filehandle" is
caused
  >> by some typeglob magic in cacheout_open()​:
  >
  > While I'm not sure the use of caller(1) is correct, I believe that to be
  > an orthoganal issue.

You're right.

  Thanks, Kai

@p5pRT
Copy link
Author

p5pRT commented Apr 8, 2005

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

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

No branches or pull requests

1 participant