AnyEvent
view release on metacpan or search on metacpan
lib/AnyEvent/Util.pm view on Meta::CPAN
}
=item $guard = guard { CODE }
This function creates a special object that, when destroyed, will execute
the code block.
This is often handy in continuation-passing style code to clean up some
resource regardless of where you break out of a process.
The L<Guard> module will be used to implement this function, if it is
available. Otherwise a pure-perl implementation is used.
While the code is allowed to throw exceptions in unusual conditions, it is
not defined whether this exception will be reported (at the moment, the
Guard module and AnyEvent's pure-perl implementation both try to report
the error and continue).
You can call one method on the returned object:
=item $guard->cancel
This simply causes the code block not to be invoked: it "cancels" the
guard.
=cut
BEGIN {
if (!$ENV{PERL_ANYEVENT_AVOID_GUARD} && eval { require Guard; $Guard::VERSION >= 0.5 }) {
*guard = \&Guard::guard;
AE::log 8 => "Using Guard module to implement guards.";
} else {
*AnyEvent::Util::guard::DESTROY = sub {
local $@;
eval {
local $SIG{__DIE__};
${$_[0]}->();
};
AE::log 4 => "Runtime error in AnyEvent::guard callback: $@" if $@;
};
*AnyEvent::Util::guard::cancel = sub ($) {
${$_[0]} = sub { };
};
*guard = sub (&) {
bless \(my $cb = shift), "AnyEvent::Util::guard"
};
AE::log 8 => "Using pure-perl guard implementation.";
}
}
=item AnyEvent::Util::close_all_fds_except @fds
This rarely-used function simply closes all file descriptors (or tries to)
of the current process except the ones given as arguments.
When you want to start a long-running background server, then it is often
beneficial to do this, as too many C-libraries are too stupid to mark
their internal fd's as close-on-exec.
The function expects to be called shortly before an C<exec> call.
Example: close all fds except 0, 1, 2.
close_all_fds_except 0, 2, 1;
=cut
sub close_all_fds_except {
my %except; @except{@_} = ();
require POSIX unless $POSIX::VERSION;
# some OSes have a usable /dev/fd, sadly, very few
if ($^O =~ /(freebsd|cygwin|linux)/) {
# netbsd, openbsd, solaris have a broken /dev/fd
my $dir;
if (opendir $dir, "/dev/fd" or opendir $dir, "/proc/self/fd") {
my @fds = sort { $a <=> $b } grep /^\d+$/, readdir $dir;
# broken OS's have device nodes for 0..63 usually, solaris 0..255
if (@fds < 20 or "@fds" ne join " ", 0..$#fds) {
# assume the fds array is valid now
exists $except{$_} or POSIX::close ($_)
for @fds;
return;
}
}
}
my $fd_max = eval { POSIX::sysconf (POSIX::_SC_OPEN_MAX ()) - 1 } || 1023;
exists $except{$_} or POSIX::close ($_)
for 0..$fd_max;
}
=item $cv = run_cmd $cmd, key => value...
Run a given external command, potentially redirecting file descriptors and
return a condition variable that gets sent the exit status (like C<$?>)
when the program exits I<and> all redirected file descriptors have been
exhausted.
The C<$cmd> is either a single string, which is then passed to a shell, or
an arrayref, which is passed to the C<execvp> function (the first array
element is used both for the executable name and argv[0]).
The key-value pairs can be:
=over 4
=item ">" => $filename
Redirects program standard output into the specified filename, similar to C<<
>filename >> in the shell.
=item ">" => \$data
( run in 0.629 second using v1.01-cache-2.11-cpan-f56aa216473 )