do 'file' -- when is file closed?

B

Brad Baxter

I am attempting to track down a "Too many open files"
situation in apache. This has led me to suspect some
of my Perl code, which is loaded by mod_rewrite from a
line like the following:

RewriteMap ggpd_do prg:/.../ggpd_do

.... and the script ggpd_do is then resident in memory
while apache is running.

Perl question: If a script like the following were loaded
as described above:

#!/usr/local/bin/perl -T
use warnings;
use strict;

$ENV{PATH} = '';

while( <STDIN> ) {
print get_file( $_ );
}

sub get_file {
my $file = shift;
chomp $file;
$file = $1 if /^(\w+)$/;
return '' unless $file;
my $ret = do "./$file";
return '' unless $ret;
return $ret;
}

.... when would "./$file" be closed? Right after 'do'? After
the script ends (which it wouldn't normally)?

Should I suspect code like this as a possible cause
for a "Too many open files" error?

Thanks,
 
X

xhoster

Brad Baxter said:
Perl question: If a script like the following were loaded
as described above:

#!/usr/local/bin/perl -T
use warnings;
use strict;

$ENV{PATH} = '';

while( <STDIN> ) {
print get_file( $_ );
}

sub get_file {
my $file = shift;
chomp $file;
$file = $1 if /^(\w+)$/;
return '' unless $file;
my $ret = do "./$file";
return '' unless $ret;
return $ret;
}

... when would "./$file" be closed? Right after 'do'? After
the script ends (which it wouldn't normally)?

I imagine this could be version/OS specific. On my machine, it closes
immediately after the do:

$ strace perl -wle 'use strict; defined do "./empty.pl" or die "1:$!"; \
defined do "./fooooo.pl" or die "2:$!"'


last few lines of the output:
.....
open("./empty.pl", O_RDONLY|O_LARGEFILE) = 3
....
read(3, "\n1;\n", 4096) = 4
read(3, "", 4096) = 0
close(3) = 0
open("./fooooo.pl", O_RDONLY|O_LARGEFILE) = -1
ENOENT (No such file or directory)
write(2, "2:No such file or directory at -"...,
422:No such file or directory at -e line 1.
) = 42
exit_group(2) = ?



So the file empty.pl (which, despite it's name, contains "1;") is opened,
read and closed, before the next statemnet, the non-existant file
fooooo.pl, is attempted.



Xho
 
D

Dr.Ruud

Brad Baxter schreef:
sub get_file {
my $file = shift;
chomp $file;
$file = $1 if /^(\w+)$/;

That regex works on $_, so I assume that you meant

$file = $file if file ~= /^\w+$/;
;)
return '' unless $file;
my $ret = do "./$file";
return '' unless $ret;
return $ret;
}

I guess this does about the same:

sub get_file {
chomp( my $file = shift );
return if ( $file !~ /^\w+$/ );
my $ret;
return $ret if ( $ret = do "./$file" );
return;
}

It is using a plain <return> in stead of <return ''>, which is often
better.
 
B

Brad Baxter

I imagine this could be version/OS specific. On my machine, it closes
immediately after the do:

$ strace perl -wle 'use strict; defined do "./empty.pl" or die "1:$!"; \
defined do "./fooooo.pl" or die "2:$!"'


last few lines of the output:
....
open("./empty.pl", O_RDONLY|O_LARGEFILE) = 3
...
read(3, "\n1;\n", 4096) = 4
read(3, "", 4096) = 0
close(3) = 0
open("./fooooo.pl", O_RDONLY|O_LARGEFILE) = -1
ENOENT (No such file or directory)
write(2, "2:No such file or directory at -"...,
422:No such file or directory at -e line 1.
) = 42
exit_group(2) = ?



So the file empty.pl (which, despite it's name, contains "1;") is opened,
read and closed, before the next statemnet, the non-existant file
fooooo.pl, is attempted.

Thanks for that. It's what I would have expected. Will check here.
Actually, I'll change the code to open and close explicitly anyway.
 
B

Brad Baxter

Dr.Ruud said:
Brad Baxter schreef:


That regex works on $_, so I assume that you meant

$file = $file if file ~= /^\w+$/;
;)

Good catch, but it needs to assign from $1 to untaint.
I guess this does about the same:

sub get_file {
chomp( my $file = shift );
return if ( $file !~ /^\w+$/ );
my $ret;
return $ret if ( $ret = do "./$file" );
return;
}

It is using a plain <return> in stead of <return ''>, which is often
better.

Yes, and despite that it's contrived code, there were other
mistakes. Perhaps a little better:

#!/usr/local/bin/perl -T
use warnings;
use strict;

while( <STDIN> ) {
print get_file( $_ );
}

sub get_file {
my $file = shift;
chomp $file;
if( $file =~ /^(\w+)$/ ) {
$file = $1;
}
else {
return;
}
my $ret = do "./$file";
return unless $ret;
return $ret;
}

Cheers,
 
B

Brad Baxter

I imagine this could be version/OS specific. On my machine, it closes
immediately after the do:

$ strace perl -wle 'use strict; defined do "./empty.pl" or die "1:$!"; \
defined do "./fooooo.pl" or die "2:$!"'


last few lines of the output:
....
open("./empty.pl", O_RDONLY|O_LARGEFILE) = 3
...
read(3, "\n1;\n", 4096) = 4
read(3, "", 4096) = 0
close(3) = 0
open("./fooooo.pl", O_RDONLY|O_LARGEFILE) = -1
ENOENT (No such file or directory)
write(2, "2:No such file or directory at -"...,
422:No such file or directory at -e line 1.
) = 42
exit_group(2) = ?



So the file empty.pl (which, despite it's name, contains "1;") is opened,
read and closed, before the next statemnet, the non-existant file
fooooo.pl, is attempted.

And similarly here:

This is perl, v5.8.6 built for sun4-solaris

$ truss /usr/local/bin/perl -wle 'use strict; defined do "./empty.pl"
or die "1:$!"; defined do "./fooooo.pl" or die "2:$!"'

....
open64("./empty.pl", O_RDONLY) = 3
fstat64(3, 0xFFBFCB60) = 0
fstat64(3, 0xFFBFCA08) = 0
ioctl(3, TCGETA, 0xFFBFCAEC) Err#25 ENOTTY
read(3, " 1 ;\n\n", 8192) = 4
llseek(3, 0, SEEK_CUR) = 4
read(3, 0x0012DD64, 8192) = 0
llseek(3, 0, SEEK_CUR) = 4
close(3) = 0
open64("./fooooo.pl", O_RDONLY) Err#2 ENOENT
fstat64(2, 0xFFBFF0F8) = 0
write(2, " 2 : N o s u c h f i".., 42) = 42
getcontext(0xFFBFF2B0)
setcontext(0xFFBFF2B0)
getcontext(0xFFBFF650)
_exit(2)

I'm pretty sure that answers my question.

Many thanks,
 
G

Glenn Jackman

At 2006-04-05 01:31PM said:
sub get_file {
my $file = shift;
chomp $file;
if( $file =~ /^(\w+)$/ ) {
$file = $1;
}
else {
return;
}
my $ret = do "./$file";
return unless $ret;
return $ret;
}

That's a lot of returns. How about:

sub get_file {
chomp( my $file = shift );
my $ret;
if ($file =~ /^(\w+)$/) {
$ret = do "./$1";
}
return $ret;
}
my $rc = get_file 'foo.pl';
warn "couldn't do 'foo.pl'\n" unless $rc;
 
A

A. Sinan Unur

That's a lot of returns. How about:

sub get_file {
chomp( my $file = shift );
my $ret;
if ($file =~ /^(\w+)$/) {
$ret = do "./$1";
}
return $ret;
}

I would have used

sub get_file {
# I think chomping should be done by caller, but anyway
chomp(my $file = shift);
return unless $file =~ /^(\w+)$/;
return do "./$1";
}


my $rc = get_file 'foo.pl';
warn "couldn't do 'foo.pl'\n" unless $rc;



--
--
A. Sinan Unur <[email protected]>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top