--- AnyEvent/lib/AnyEvent.pm 2011/09/02 04:41:16 1.383 +++ AnyEvent/lib/AnyEvent.pm 2013/03/01 06:03:21 1.410 @@ -417,9 +417,9 @@ =head3 Safe/Unsafe Signals -Perl signals can be either "safe" (synchronous to opcode handling) or -"unsafe" (asynchronous) - the former might get delayed indefinitely, the -latter might corrupt your memory. +Perl signals can be either "safe" (synchronous to opcode handling) +or "unsafe" (asynchronous) - the former might delay signal delivery +indefinitely, the latter might corrupt your memory. AnyEvent signal handlers are, in addition, synchronous to the event loop, i.e. they will not interrupt your running perl program but will only be @@ -428,23 +428,21 @@ =head3 Signal Races, Delays and Workarounds -Many event loops (e.g. Glib, Tk, Qt, IO::Async) do not support attaching -callbacks to signals in a generic way, which is a pity, as you cannot -do race-free signal handling in perl, requiring C libraries for -this. AnyEvent will try to do its best, which means in some cases, -signals will be delayed. The maximum time a signal might be delayed is -specified in C<$AnyEvent::MAX_SIGNAL_LATENCY> (default: 10 seconds). This -variable can be changed only before the first signal watcher is created, -and should be left alone otherwise. This variable determines how often -AnyEvent polls for signals (in case a wake-up was missed). Higher values -will cause fewer spurious wake-ups, which is better for power and CPU -saving. +Many event loops (e.g. Glib, Tk, Qt, IO::Async) do not support +attaching callbacks to signals in a generic way, which is a pity, +as you cannot do race-free signal handling in perl, requiring +C libraries for this. AnyEvent will try to do its best, which +means in some cases, signals will be delayed. The maximum time +a signal might be delayed is 10 seconds by default, but can +be overriden via C<$ENV{PERL_ANYEVENT_MAX_SIGNAL_LATENCY}> or +C<$AnyEvent::MAX_SIGNAL_LATENCY> - see the L +section for details. All these problems can be avoided by installing the optional L module, which works with most event loops. It will not work with inherently broken event loops such as L or L -(and not with L currently, as POE does its own workaround with -one-second latency). For those, you just have to suffer the delays. +(and not with L currently). For those, you just have to suffer the +delays. =head2 CHILD PROCESS WATCHERS @@ -767,6 +765,10 @@ $cv->end; + ... + + my $results = $cv->recv; + This code fragment supposedly pings a number of hosts and calls C after results for all then have have been gathered - in any order. To achieve this, the code issues a call to C when it starts @@ -811,11 +813,15 @@ in scalar context only the first one will be returned. Note that doing a blocking wait in a callback is not supported by any -event loop, that is, recursive invocation of a blocking C<< ->recv ->> is not allowed, and the C call will C if such a -condition is detected. This condition can be slightly loosened by using -L, which allows you to do a blocking C<< ->recv >> from -any thread that doesn't run the event loop itself. +event loop, that is, recursive invocation of a blocking C<< ->recv >> is +not allowed and the C call will C if such a condition is +detected. This requirement can be dropped by relying on L +, which allows you to do a blocking C<< ->recv >> from any thread +that doesn't run the event loop itself. L is loaded +automatically when L is used with L, so code does not need +to do anything special to take advantage of that: any code that would +normally block your program because it calls C, be executed in an +C thread instead without blocking other threads. Not all event models support a blocking wait - some die in that case (programs might want to do that to stay interactive), so I (1|2), higher numbers are preferred +our $MAX_SIGNAL_LATENCY = $ENV{PERL_ANYEVENT_MAX_SIGNAL_LATENCY} || 10; # executes after the BEGIN block below (tainting!) BEGIN { require "AnyEvent/constants.pl"; @@ -1261,7 +1268,7 @@ # $ENV{PERL_ANYEVENT_xxx} now valid - $VERBOSE = length $ENV{PERL_ANYEVENT_VERBOSE} ? $ENV{PERL_ANYEVENT_VERBOSE}*1 : 3; + $VERBOSE = length $ENV{PERL_ANYEVENT_VERBOSE} ? $ENV{PERL_ANYEVENT_VERBOSE}*1 : 4; my $idx; $PROTOCOL{$_} = ++$idx @@ -1305,8 +1312,9 @@ sub log($$;@) { # only load the big bloated module when we actually are about to log something - if ($_[0] <= $VERBOSE) { # also catches non-numeric levels(!) - require AnyEvent::Log; + if ($_[0] <= ($VERBOSE || 1)) { # also catches non-numeric levels(!) and fatal + local ($!, $@); + require AnyEvent::Log; # among other things, sets $VERBOSE to 9 # AnyEvent::Log overwrites this function goto &log; } @@ -1314,20 +1322,48 @@ 0 # not logged } +sub _logger($;$) { + my ($level, $renabled) = @_; + + $$renabled = $level <= $VERBOSE; + + my $logger = [(caller)[0], $level, $renabled]; + + $AnyEvent::Log::LOGGER{$logger+0} = $logger; + +# return unless defined wantarray; +# +# require AnyEvent::Util; +# my $guard = AnyEvent::Util::guard (sub { +# # "clean up" +# delete $LOGGER{$logger+0}; +# }); +# +# sub { +# return 0 unless $$renabled; +# +# $guard if 0; # keep guard alive, but don't cause runtime overhead +# require AnyEvent::Log unless $AnyEvent::Log::VERSION; +# package AnyEvent::Log; +# _log ($logger->[0], $level, @_) # logger->[0] has been converted at load time +# } +} + if (length $ENV{PERL_ANYEVENT_LOG}) { require AnyEvent::Log; # AnyEvent::Log does the thing for us } our @models = ( - [EV:: => AnyEvent::Impl::EV:: , 1], - [AnyEvent::Loop:: => AnyEvent::Impl::Perl:: , 1], + [EV:: => AnyEvent::Impl::EV::], + [AnyEvent::Loop:: => AnyEvent::Impl::Perl::], # everything below here will not (normally) be autoprobed # as the pure perl backend should work everywhere # and is usually faster - [Event:: => AnyEvent::Impl::Event::, 1], - [Glib:: => AnyEvent::Impl::Glib:: , 1], # becomes extremely slow with many watchers + [Irssi:: => AnyEvent::Impl::Irssi::], # Irssi has a bogus "Event" package, so msut be near the top + [Event:: => AnyEvent::Impl::Event::], # slow, stable + [Glib:: => AnyEvent::Impl::Glib::], # becomes extremely slow with many watchers + # everything below here should not be autoloaded [Event::Lib:: => AnyEvent::Impl::EventLib::], # too buggy - [Irssi:: => AnyEvent::Impl::Irssi::], # Irssi has a bogus "Event" package [Tk:: => AnyEvent::Impl::Tk::], # crashes with many handles [Qt:: => AnyEvent::Impl::Qt::], # requires special main program [POE::Kernel:: => AnyEvent::Impl::POE::], # lasciate ogni speranza @@ -1366,6 +1402,14 @@ sub detect() { return $MODEL if $MODEL; # some programs keep references to detect + # IO::Async::Loop::AnyEvent is extremely evil, refuse to work with it + # the author knows about the problems and what it does to AnyEvent as a whole + # (and the ability of others to use AnyEvent), but simply wants to abuse AnyEvent + # anyway. + AnyEvent::log fatal => "IO::Async::Loop::AnyEvent detected - that module is broken by\n" + . "design, abuses internals and breaks AnyEvent - will not continue." + if exists $INC{"IO/Async/Loop/AnyEvent.pm"}; + local $!; # for good measure local $SIG{__DIE__}; # we use eval @@ -1383,10 +1427,10 @@ my $model = $1; $model = "AnyEvent::Impl::$model" unless $model =~ s/::$//; if (eval "require $model") { - AnyEvent::log 7 => "loaded model '$model' (forced by \$ENV{PERL_ANYEVENT_MODEL}), using it."; + AnyEvent::log 7 => "Loaded model '$model' (forced by \$ENV{PERL_ANYEVENT_MODEL}), using it."; $MODEL = $model; } else { - AnyEvent::log 5 => "unable to load model '$model' (from \$ENV{PERL_ANYEVENT_MODEL}):\n$@"; + AnyEvent::log 4 => "Unable to load model '$model' (from \$ENV{PERL_ANYEVENT_MODEL}):\n$@"; } } @@ -1396,9 +1440,11 @@ my ($package, $model) = @$_; if (${"$package\::VERSION"} > 0) { if (eval "require $model") { - AnyEvent::log 7 => "autodetected model '$model', using it."; + AnyEvent::log 7 => "Autodetected model '$model', using it."; $MODEL = $model; last; + } else { + AnyEvent::log 8 => "Detected event loop $package, but cannot load '$model', skipping: $@"; } } } @@ -1406,21 +1452,20 @@ unless ($MODEL) { # try to autoload a model for (@REGISTRY, @models) { - my ($package, $model, $autoload) = @$_; + my ($package, $model) = @$_; if ( - $autoload - and eval "require $package" + eval "require $package" and ${"$package\::VERSION"} > 0 and eval "require $model" ) { - AnyEvent::log 7 => "autoloaded model '$model', using it."; + AnyEvent::log 7 => "Autoloaded model '$model', using it."; $MODEL = $model; last; } } $MODEL - or die "AnyEvent: backend autodetection failed - did you properly install AnyEvent?"; + or AnyEvent::log fatal => "Backend autodetection failed - did you properly install AnyEvent?"; } } @@ -1577,13 +1622,13 @@ *time = sub { Time::HiRes::time () }; *AE::time = \& Time::HiRes::time ; *now = \&time; - AnyEvent::log 8 => "AnyEvent: using Time::HiRes for sub-second timing accuracy."; + AnyEvent::log 8 => "using Time::HiRes for sub-second timing accuracy."; # if (eval "use POSIX (); (POSIX::times())... } else { *time = sub { CORE::time }; *AE::time = sub (){ CORE::time }; *now = \&time; - AnyEvent::log 3 => "using built-in time(), WARNING, no sub-second resolution!"; + AnyEvent::log 3 => "Using built-in time(), no sub-second resolution!"; } }; die if $@; @@ -1687,13 +1732,13 @@ eval q{ # poor man's autoloading {} # probe for availability of Async::Interrupt if (_have_async_interrupt) { - AnyEvent::log 8 => "using Async::Interrupt for race-free signal handling."; + AnyEvent::log 8 => "Using Async::Interrupt for race-free signal handling."; $SIGPIPE_R = new Async::Interrupt::EventPipe; $SIG_IO = AE::io $SIGPIPE_R->fileno, 0, \&_signal_exec; } else { - AnyEvent::log 8 => "using emulated perl signal handling with latency timer."; + AnyEvent::log 8 => "Using emulated perl signal handling with latency timer."; if (AnyEvent::WIN32) { require AnyEvent::Util; @@ -2039,28 +2084,28 @@ =item C -By default, AnyEvent will only log messages with loglevel C<3> -(C) or higher (see L). You can set this -environment variable to a numerical loglevel to make AnyEvent more (or -less) talkative. +By default, AnyEvent will log messages with loglevel C<4> (C) or +higher (see L). You can set this environment variable to a +numerical loglevel to make AnyEvent more (or less) talkative. If you want to do more than just set the global logging level you should have a look at C, which allows much more complex specifications. When set to C<0> (C), then no messages whatsoever will be logged with -the default logging settings. +everything else at defaults. -When set to C<5> or higher (C), causes AnyEvent to warn about -unexpected conditions, such as not being able to load the event model -specified by C, or a guard callback throwing an -exception - this is the minimum recommended level. +When set to C<5> or higher (C), AnyEvent warns about unexpected +conditions, such as not being able to load the event model specified by +C, or a guard callback throwing an exception - this +is the minimum recommended level for use during development. -When set to C<7> or higher (info), cause AnyEvent to report which event model it +When set to C<7> or higher (info), AnyEvent reports which event model it chooses. -When set to C<8> or higher (debug), then AnyEvent will report extra information on -which optional modules it loads and how it implements certain features. +When set to C<8> or higher (debug), then AnyEvent will report extra +information on which optional modules it loads and how it implements +certain features. =item C @@ -2077,8 +2122,8 @@ Note that specifying this environment variable causes the L module to be loaded, while C does not, so only -using the latter saves a few hundred kB of memory until the first message -is being logged. +using the latter saves a few hundred kB of memory unless a module +explicitly needs the extra features of AnyEvent::Log. =item C @@ -2143,6 +2188,14 @@ PERL_ANYEVENT_MODEL=Perl perl ... +=item C + +The current file I/O model - see L for more info. + +At the moment, only C (small, pure-perl, synchronous) and +C (truly asynchronous) are supported. The default is C if +L can be loaded, otherwise it is C. + =item C Used by both L and L to determine preferences @@ -2191,6 +2244,28 @@ resolver - this is the maximum number of parallel DNS requests that are sent to the DNS server. +=item C + +Perl has inherently racy signal handling (you can basically choose between +losing signals and memory corruption) - pure perl event loops (including +C, when C isn't available) therefore +have to poll regularly to avoid losing signals. + +Some event loops are racy, but don't poll regularly, and some event loops +are written in C but are still racy. For those event loops, AnyEvent +installs a timer that regularly wakes up the event loop. + +By default, the interval for this timer is C<10> seconds, but you can +override this delay with this environment variable (or by setting +the C<$AnyEvent::MAX_SIGNAL_LATENCY> variable before creating signal +watchers). + +Lower values increase CPU (and energy) usage, higher values can introduce +long delays when reaping children or waiting for signals. + +The L module, if available, will be used to avoid this +polling (with most event loops). + =item C The absolute path to a F-style file to use instead of @@ -2856,6 +2931,16 @@ pure-perl event loop (L) will additionally load it to try to use a monotonic clock for timing stability. +=item L (and L) + +The default implementation of L is to do I/O synchronously, +stopping programs while they access the disk, which is fine for a lot of +programs. + +Installing AnyEvent::AIO (and its IO::AIO dependency) makes it switch to +a true asynchronous implementation, so event processing can continue even +while waiting for disk I/O. + =back @@ -2948,6 +3033,8 @@ Non-blocking handles, pipes, stream sockets, TCP clients and servers: L, L, L. +Asynchronous File I/O: L. + Asynchronous DNS: L. Thread support: L, L, L, L. @@ -2959,7 +3046,7 @@ =head1 AUTHOR Marc Lehmann - http://home.schmorp.de/ + http://anyevent.schmorp.de =cut