English 中文(简体)
如何在垂直方案中找到开放的全球档案
原标题:How to find open global filehandles in a perl program

我仅追踪一个问题,即我不得不关闭我的阿帕奇特文的所有公开档案。 我将问题追踪到Parse:RecDescent。

#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say/;
$|++;

print "Content-Type: text/plain

";

use Parse::RecDescent;

say "$$: pre-fork: ". time;

if(my $pid = fork) {
    # parent
    say "$$: return immediately: ". time;
}
else {
    # child 
    say "$$: kicked off big process: ". time;
    close STDIN;
    close STDOUT;
    close STDERR;
    # close *{ Parse::RecDescent::ERROR };
    sleep 5;
}

我的问题是,我如何找到所有公开的一揽子档案。

I know fileno will return a counter for an open filehandle. Is there a way to do a reverse lookup for these, or close filehandles by their fileno counter?

最佳回答

在某些系统中,通过<代码>退还的名录”/proc/$/fd/"载有公开档案说明者名单。 您可使用<代码>POSIX:close予以关闭。

# close all filehandles
for (glob "/proc/$$/fd/*") { POSIX::close($1) if m{/(d+)$}; }
问题回答

在追踪关于高血清精度的近距离细节时,我认为,如果你只是执行另一个程序的话,你需要做的是:STDERR

   $SYSTEM_FD_MAX
   $^F     The maximum system file descriptor, ordinarily 2.
           System file descriptors are passed to exec()ed
           processes, while higher file descriptors are not.
           Also, during an open(), system file descriptors are
           preserved even if the open() fails.  (Ordinary file
           descriptors are closed before the open() is
           attempted.)  The close-on-exec status of a file
           descriptor will be decided according to the value of
           $^F when the corresponding file, pipe, or socket was
           opened, not the time of the exec().

当然,如果你的长期任务不需要<条码>execve(2)的运行,那么近身边的旗帜就赢得了你们的帮助。 所有这些都取决于<条码>第5条是备用的。

你们可以通过一揽子树 des:

use strict;
use warnings;
use constant BREAK_DESCENT => {};

use Carp    qw<croak>;
use English qw<$EVAL_ERROR>; # $@

sub break_descent { 
    return BREAK_DESCENT if defined wantarray;
    die BREAK_DESCENT;
}

sub _package_descend {
    my ( $package_name, $stash, $selector ) = @_;
    my $in_main     = $package_name =~ m/^(?:main)?::$/; 
    foreach my $name ( keys %$stash ) { 
        next if ( $in_main and $name eq  main::  );
        my $full_name = $package_name . $name;
        local $_      = do { no strict  refs ; *$full_name; };
        my $return 
            = $name =~ m/::$/ 
            ? _package_descend( $full_name, *{$_}{HASH}, $selector ) 
            : $selector->( $package_name, $name => $_ )
            ;
        return BREAK_DESCENT if ( ref( $return ) and $return == BREAK_DESCENT );
    }
    return;
}

sub package_walk {

    my ( $package_name, $selector ) 
        = @_ == 1 ? (  :: , shift )
        :           @_
        ;

    $package_name  .=  ::  unless substr( $package_name, -2 ) eq  :: ;
    local $EVAL_ERROR;

    eval { 
       no strict  refs ;
       _package_descend( $package_name, \%$package_name, $selector ); 
    };

    return unless $EVAL_ERROR;
    return if     do { no warnings  numeric ; $EVAL_ERROR == BREAK_DESCENT; };

    say STDERR $EVAL_ERROR;
    croak(  Failed in selector!  );
}

package_walk( sub { 
    my ( $pkg, $name ) = @_;
    #say "$pkg$name";
    # to not close handles in ::main::
    #return if $pkg =~  m/^(?:main)?::$/;
    # use IO::Handle methods...
    map { defined and $_->opened and $_->close } *{$_}{IO}; 
});

什么是全球压倒的<代码>开放<>/编码>,其文本保留了它所创造的所有业务的清单? 这可能是一个开端:

use Scalar::Util  weaken ;
use Symbol ();
my @handles;
BEGIN {
    *CORE::GLOBAL::open = sub (*;$@) {
        if (defined $_[0] and not ref $_[0]) {
            splice @_, 0, 1, Symbol::qualify_to_ref($_[0])
        }
        my $ret =
            @_ == 1 ? CORE::open $_[0] :
            @_ == 2 ? CORE::open $_[0], $_[1] :
                      CORE::open $_[0], $_[1], @_[2 .. $#_];
        if ($ret) {
            push @handles, $_[0];
            weaken $handles[-1];
        }
        $ret
    }
}

sub close_all_handles {
    $_ and eval {close $_} for @handles
}

open FH, $0;

say scalar <FH>;  # prints "use Scalar::Util  weaken ;"

close_all_handles;

say scalar <FH>;  # error: readline() on closed file handle

这应当赶上所有的全球业务,甚至能够产生但从未清理过的任何弹性处理(由于循环提及或其他原因)。

如在请上<条码>使用代码:RecDescent之前,将这一条放在首位。 然后,该模块将推翻<代码>开放<>/代码>的电话。

我最后采用“快车”的建议,但我对“Axeman”方法感兴趣。 此处为简化版本。

# Find all file-handles in packages.
my %seen;
sub recurse {
    no strict  refs ;
    my $package = shift or return;
    return if $seen{$package}++;

    for my $part (sort keys %{$package}) {
        if (my $fileno = fileno($package.$part)) {
            print $package.$part." => $fileno
";
        }
    }
    for my $part (grep /::/, sort keys %{$package}) {
        (my $sub_pkg = $package.$part) =~ s/main:://;
        recurse($sub_pkg);
    }
}
recurse( main:: );




相关问题
Why does my chdir to a filehandle not work in Perl?

When I try a "chdir" with a filehandle as argument, "chdir" returns 0 and a pwd returns still the same directory. Should that be so? I tried this, because in the documentation to chdir I found: "...

How do I use GetOptions to get the default argument?

I ve read the doc for GetOptions but I can t seem to find what I need... (maybe I am blind) What I want to do is to parse command line like this myperlscript.pl -mode [sth] [inputfile] I can use ...

Object-Oriented Perl constructor syntax and named parameters

I m a little confused about what is going on in Perl constructors. I found these two examples perldoc perlbot. package Foo; #In Perl, the constructor is just a subroutine called new. sub new { #I ...

Where can I find object-oriented Perl tutorials? [closed]

A Google search yields a number of results - but which ones are the best? The Perl site appears to contain two - perlboot and perltoot. I m reading these now, but what else is out there? Note: I ve ...