--- AnyEvent/lib/AnyEvent.pm 2011/08/13 02:35:32 1.358 +++ AnyEvent/lib/AnyEvent.pm 2011/08/24 23:59:10 1.371 @@ -2,8 +2,8 @@ AnyEvent - the DBI of event loop programming -EV, Event, Glib, Tk, Perl, Event::Lib, Irssi, rxvt-unicode, IO::Async, Qt -and POE are various supported event loops/environments. +EV, Event, Glib, Tk, Perl, Event::Lib, Irssi, rxvt-unicode, IO::Async, Qt, +FLTK and POE are various supported event loops/environments. =head1 SYNOPSIS @@ -936,6 +936,10 @@ have created an AnyEvent watcher anyway, that is, as late as possible at runtime, and not e.g. during initialisation of your module. +The effect of calling this function is as if a watcher had been created +(specifically, actions that happen "when the first watcher is created" +happen when calling detetc as well). + If you need to do some initialisation before AnyEvent watchers are created, use C. @@ -1047,6 +1051,16 @@ AnyEvent::postpone { $cb->(undef) }, return # signal error to callback, later if $some_error_condition; +=item AnyEvent::log $level, $msg[, @args] + +Log the given C<$msg> at the given C<$level>. + +Loads AnyEvent::Log on first use and calls C - +consequently, look at the L documentation for details. + +If you want to sprinkle loads of logging calls around your code, consider +creating a logger callback with the C function. + =back =head1 WHAT TO DO IN A MODULE @@ -1112,9 +1126,12 @@ =head1 OTHER MODULES The following is a non-exhaustive list of additional modules that use -AnyEvent as a client and can therefore be mixed easily with other AnyEvent -modules and other event loops in the same program. Some of the modules -come as part of AnyEvent, the others are available via CPAN. +AnyEvent as a client and can therefore be mixed easily with other +AnyEvent modules and other event loops in the same program. Some of the +modules come as part of AnyEvent, the others are available via CPAN (see +L for +a longer non-exhaustive list), and the list is heavily biased towards +modules of the AnyEvent author himself :) =over 4 @@ -1204,7 +1221,7 @@ use Carp (); -our $VERSION = '5.34'; +our $VERSION = '6.01'; our $MODEL; our @ISA; @@ -1221,8 +1238,13 @@ delete @ENV{grep /^PERL_ANYEVENT_/, keys %ENV} if ${^TAINT}; - $VERBOSE = $ENV{PERL_ANYEVENT_VERBOSE}*1; + $ENV{"PERL_ANYEVENT_$_"} = $ENV{"AE_$_"} + for grep s/^AE_// && !exists $ENV{"PERL_ANYEVENT_$_"}, keys %ENV; + + @ENV{grep /^PERL_ANYEVENT_/, keys %ENV} = () + if ${^TAINT}; + $VERBOSE = $ENV{PERL_ANYEVENT_VERBOSE}*1; } our $MAX_SIGNAL_LATENCY = 10; @@ -1270,6 +1292,12 @@ () } +sub log($$;@) { + require AnyEvent::Log; + # AnyEvent::Log overwrites this function + goto &log; +} + our @models = ( [EV:: => AnyEvent::Impl::EV:: , 1], [AnyEvent::Loop:: => AnyEvent::Impl::Perl:: , 1], @@ -1290,11 +1318,34 @@ [FLTK:: => AnyEvent::Impl::FLTK2::], ); +our @isa_hook; + +sub _isa_set { + my @pkg = ("AnyEvent", (map $_->[0], grep defined, @isa_hook), $MODEL); + + @{"$pkg[$_-1]::ISA"} = $pkg[$_] + for 1 .. $#pkg; + + grep $_ && $_->[1], @isa_hook + and AE::_reset (); +} + +# used for hooking AnyEvent::Strict and AnyEvent::Debug::Wrap into the class hierarchy +sub _isa_hook($$;$) { + my ($i, $pkg, $reset_ae) = @_; + + $isa_hook[$i] = $pkg ? [$pkg, $reset_ae] : undef; + + _isa_set; +} + # all autoloaded methods reserve the complete glob, not just the method slot. # due to bugs in perls method cache implementation. our @methods = qw(io timer time now now_update signal child idle condvar); sub detect() { + return $MODEL if $MODEL; # some programs keep references to detect + local $!; # for good measure local $SIG{__DIE__}; # we use eval @@ -1313,9 +1364,10 @@ $model = "AnyEvent::Impl::$model" unless $model =~ s/::$//; if (eval "require $model") { $MODEL = $model; - warn "AnyEvent: loaded model '$model' (forced by \$ENV{PERL_ANYEVENT_MODEL}), using it.\n" if $VERBOSE >= 2; + AnyEvent::log 7 => "loaded model '$model' (forced by \$ENV{PERL_ANYEVENT_MODEL}), using it." + if $VERBOSE >= 7; } else { - warn "AnyEvent: unable to load model '$model' (from \$ENV{PERL_ANYEVENT_MODEL}):\n$@" if $VERBOSE; + AnyEvent::log warn => "unable to load model '$model' (from \$ENV{PERL_ANYEVENT_MODEL}):\n$@"; } } @@ -1326,7 +1378,8 @@ if (${"$package\::VERSION"} > 0) { if (eval "require $model") { $MODEL = $model; - warn "AnyEvent: autodetected model '$model', using it.\n" if $VERBOSE >= 2; + AnyEvent::log 7 => "autodetected model '$model', using it." + if $VERBOSE >= 7; last; } } @@ -1343,13 +1396,14 @@ and eval "require $model" ) { $MODEL = $model; - warn "AnyEvent: autoloaded model '$model', using it.\n" if $VERBOSE >= 2; + AnyEvent::log 7 => "autoloaded model '$model', using it." + if $VERBOSE >= 7; last; } } $MODEL - or die "AnyEvent: backend autodetection failed - did you properly install AnyEvent?\n"; + or die "AnyEvent: backend autodetection failed - did you properly install AnyEvent?"; } } @@ -1358,7 +1412,6 @@ undef @REGISTRY; push @{"$MODEL\::ISA"}, "AnyEvent::Base"; - unshift @ISA, $MODEL; # now nuke some methods that are overridden by the backend. # SUPER usage is not allowed in these. @@ -1367,6 +1420,14 @@ if defined &{"$MODEL\::$_"}; } + _isa_set; + + # we're officially open! + + if (length $ENV{PERL_ANYEVENT_LOG}) { + require AnyEvent::Log; # AnyEvent::Log does the thing for us + } + if ($ENV{PERL_ANYEVENT_STRICT}) { require AnyEvent::Strict; } @@ -1376,14 +1437,20 @@ AnyEvent::Debug::wrap ($ENV{PERL_ANYEVENT_DEBUG_WRAP}); } - if (exists $ENV{PERL_ANYEVENT_DEBUG_SHELL}) { + if (length $ENV{PERL_ANYEVENT_DEBUG_SHELL}) { require AnyEvent::Socket; require AnyEvent::Debug; - my ($host, $service) = AnyEvent::Socket::parse_hostport ($ENV{PERL_ANYEVENT_DEBUG_SHELL}); + my $shell = $ENV{PERL_ANYEVENT_DEBUG_SHELL}; + $shell =~ s/\$\$/$$/g; + + my ($host, $service) = AnyEvent::Socket::parse_hostport ($shell); $AnyEvent::Debug::SHELL = AnyEvent::Debug::shell ($host, $service); } + # now the anyevent environment is set up as the user told us to, so + # call the actual user code - post detects + (shift @post_detect)->() while @post_detect; undef @post_detect; @@ -1479,6 +1546,7 @@ } *postpone = \&AnyEvent::postpone; + *log = \&AnyEvent::log; }; die if $@; } @@ -1493,15 +1561,18 @@ eval q{ # poor man's autoloading {} # probe for availability of Time::HiRes if (eval "use Time::HiRes (); Time::HiRes::time (); 1") { - warn "AnyEvent: using Time::HiRes for sub-second timing accuracy.\n" if $VERBOSE >= 8; - *AE::time = \&Time::HiRes::time; + AnyEvent::log 8 => "AnyEvent: using Time::HiRes for sub-second timing accuracy." + if $AnyEvent::VERBOSE >= 8; + *time = sub { Time::HiRes::time () }; + *AE::time = \& Time::HiRes::time ; # if (eval "use POSIX (); (POSIX::times())... } else { - warn "AnyEvent: using built-in time(), WARNING, no sub-second resolution!\n" if $VERBOSE; - *AE::time = sub (){ time }; # epic fail + AnyEvent::log critical => "using built-in time(), WARNING, no sub-second resolution!"; + *time = sub { CORE::time }; + *AE::time = sub (){ CORE::time }; } - *time = sub { AE::time }; # different prototypes + *now = \&time; }; die if $@; @@ -1509,7 +1580,6 @@ } *now = \&time; - sub now_update { } sub _poll { @@ -1605,13 +1675,15 @@ eval q{ # poor man's autoloading {} # probe for availability of Async::Interrupt if (_have_async_interrupt) { - warn "AnyEvent: using Async::Interrupt for race-free signal handling.\n" if $VERBOSE >= 8; + AnyEvent::log 8 => "using Async::Interrupt for race-free signal handling." + if $AnyEvent::VERBOSE >= 8; $SIGPIPE_R = new Async::Interrupt::EventPipe; $SIG_IO = AE::io $SIGPIPE_R->fileno, 0, \&_signal_exec; } else { - warn "AnyEvent: using emulated perl signal handling with latency timer.\n" if $VERBOSE >= 8; + AnyEvent::log 8 => "using emulated perl signal handling with latency timer." + if $AnyEvent::VERBOSE >= 8; if (AnyEvent::WIN32) { require AnyEvent::Util; @@ -1915,12 +1987,43 @@ =head1 ENVIRONMENT VARIABLES -The following environment variables are used by this module or its -submodules. +AnyEvent supports a number of environment variables that tune the +runtime behaviour. They are usually evaluated when AnyEvent is +loaded, initialised, or a submodule that uses them is loaded. Many of +them also cause AnyEvent to load additional modules - for example, +C causes the L module to be +loaded. + +All the environment variables documented here start with +C, which is what AnyEvent considers its own +namespace. Other modules are encouraged (but by no means required) to use +C if they have registered the AnyEvent::Submodule +namespace on CPAN, for any submodule. For example, L could +be expected to use C (it should not access env +variables starting with C, see below). + +All variables can also be set via the C prefix, that is, instead +of setting C you can also set C. In +case there is a clash btween anyevent and another program that uses +C you can set the corresponding C +variable to the empty string, as those variables take precedence. + +When AnyEvent is first loaded, it copies all C env variables +to their C counterpart unless that variable already +exists. If taint mode is on, then AnyEvent will remove I environment +variables starting with C from C<%ENV> (or replace them +with C or the empty string, if the corresaponding C variable +is set). + +The exact algorithm is currently: + + 1. if taint mode enabled, delete all PERL_ANYEVENT_xyz variables from %ENV + 2. copy over AE_xyz to PERL_ANYEVENT_xyz unless the latter alraedy exists + 3. if taint mode enabled, set all PERL_ANYEVENT_xyz variables to undef. -Note that AnyEvent will remove I environment variables starting with -C from C<%ENV> when it is loaded while taint mode is -enabled. +This ensures that child processes will not see the C variables. + +The following environment variables are currently known to AnyEvent: =over 4 @@ -1928,18 +2031,35 @@ By default, AnyEvent will be completely silent except in fatal conditions. You can set this environment variable to make AnyEvent more -talkative. +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<1> or higher, causes AnyEvent to warn about unexpected +When set to C<5> or higher, causes AnyEvent to warn about unexpected conditions, such as not being able to load the event model specified by C. -When set to C<2> or higher, cause AnyEvent to report to STDERR which event +When set to C<7> or higher, cause AnyEvent to report to STDERR which event model it chooses. When set to C<8> or higher, then AnyEvent will report extra information on which optional modules it loads and how it implements certain features. +=item C + +Accepts rather complex logging specifications. For example, you could log +all C messages of some module to stderr, warnings and above to +stderr, and errors and above to syslog, with: + + PERL_ANYEVENT_LOG=Some::Module=debug,+log:filter=warn,+%syslog:%syslog=error,syslog + +For the rather extensive details, see L. + +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. + =item C AnyEvent does not do much argument checking by default, as thorough @@ -1957,15 +2077,20 @@ =item C -If this env variable is set, then its contents will be -interpreted by C and an -C is bound on that port. The shell object is saved -in C<$AnyEvent::Debug::SHELL>. +If this env variable is set, then its contents will be interpreted by +C (after replacing every occurance of +C<$$> by the process pid) and an C is bound on +that port. The shell object is saved in C<$AnyEvent::Debug::SHELL>. + +This takes place when the first watcher is created. For example, to bind a debug shell on a unix domain socket in -F, you could use this: +F<< /tmp/debug.sock >>, you could use this: - PERL_ANYEVENT_DEBUG_SHELL=unix/:/tmp/debug.sock perlprog + PERL_ANYEVENT_DEBUG_SHELL=/tmp/debug\$\$.sock perlprog + +Note that creating sockets in F is very unsafe on multiuser +systems. =item C @@ -2015,10 +2140,10 @@ =item C -Used by L to decide whether to use the EDNS0 extension -for DNS. This extension is generally useful to reduce DNS traffic, but -some (broken) firewalls drop such DNS packets, which is why it is off by -default. +Used by L to decide whether to use the EDNS0 extension for +DNS. This extension is generally useful to reduce DNS traffic, especially +when DNSSEC is involved, but some (broken) firewalls drop such DNS +packets, which is why it is off by default. Setting this variable to C<1> will cause L to announce EDNS0 in its DNS requests. @@ -2036,16 +2161,16 @@ =item C -The file to use instead of F (or OS-specific -configuration) in the default resolver. When set to the empty string, no -default config will be used. +The absolute path to a F-style file to use instead of +F (or the OS-specific configuration) in the default +resolver, or the empty string to select the default configuration. =item C, C. When neither C nor C was specified during L context creation, and either of these environment -variables exist, they will be used to specify CA certificate locations -instead of a system-dependent default. +variables are nonempty, they will be used to specify CA certificate +locations instead of a system-dependent default. =item C and C @@ -2387,7 +2512,7 @@ =item * The overhead AnyEvent adds is usually much smaller than the overhead of the actual event loop, only with extremely fast event loops such as EV -adds AnyEvent significant overhead. +does AnyEvent add significant overhead. =item * You should avoid POE like the plague if you want performance or reasonable memory usage. @@ -2772,17 +2897,23 @@ FAQ: L. -Utility functions: L. +Utility functions: L (misc. grab-bag), L +(simply logging). + +Development/Debugging: L (stricter checking), +L (interactive shell, watcher tracing). -Event modules: L, L, L, L, -L, L, L, L, L, L, L. +Supported event modules: L, L, L, +L, L, L, L, L, L, +L, L, L. Implementations: L, L, L, L, L, L, L, -L, L, L. +L, L, L, +L. -Non-blocking file handles, sockets, TCP clients and +Non-blocking handles, pipes, stream sockets, TCP clients and servers: L, L, L. Asynchronous DNS: L.