do 'file' -- when is file closed?

Discussion in 'Perl Misc' started by Brad Baxter, Apr 5, 2006.

  1. Brad Baxter

    Brad Baxter Guest

    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,

    --
    Brad
     
    Brad Baxter, Apr 5, 2006
    #1
    1. Advertising

  2. Brad Baxter

    Guest

    "Brad Baxter" <> wrote:
    ....
    >
    > 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

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Apr 5, 2006
    #2
    1. Advertising

  3. Brad Baxter

    Dr.Ruud Guest

    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.

    --
    Affijn, Ruud

    "Gewoon is een tijger."
     
    Dr.Ruud, Apr 5, 2006
    #3
  4. Brad Baxter

    Brad Baxter Guest

    wrote:
    > "Brad Baxter" <> wrote:
    > ...
    > >
    > > 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.
    >


    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.

    --
    Brad
     
    Brad Baxter, Apr 5, 2006
    #4
  5. Brad Baxter

    Brad Baxter Guest

    Dr.Ruud wrote:
    > 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+$/;
    > ;)


    Good catch, but it needs to assign from $1 to untaint.

    >
    > > 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.


    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,

    --
    Brad
     
    Brad Baxter, Apr 5, 2006
    #5
  6. Brad Baxter

    Brad Baxter Guest

    wrote:
    > 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,

    --
    Brad
     
    Brad Baxter, Apr 5, 2006
    #6
  7. At 2006-04-05 01:31PM, Brad Baxter <> wrote:
    > 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;


    --
    Glenn Jackman
    Ulterior Designer
     
    Glenn Jackman, Apr 5, 2006
    #7
  8. Glenn Jackman <> wrote in
    news::

    > At 2006-04-05 01:31PM, Brad Baxter <> wrote:
    >> 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;
    > }


    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 <>
    (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
     
    A. Sinan Unur, Apr 5, 2006
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. damezumari
    Replies:
    2
    Views:
    506
    damezumari
    Apr 27, 2006
  2. j vickroy
    Replies:
    5
    Views:
    809
    Peter Otten
    Nov 14, 2003
  3. Marco Nicosia
    Replies:
    0
    Views:
    431
    Marco Nicosia
    Feb 25, 2005
  4. edwin
    Replies:
    0
    Views:
    305
    edwin
    Apr 15, 2005
  5. Matt Kruse
    Replies:
    5
    Views:
    322
    Richard Cornford
    Sep 9, 2003
Loading...

Share This Page