State corruption in AnyEvent::Loop

Marc Lehmann schmorp at schmorp.de
Mon Jun 29 09:23:22 CEST 2020


On Sat, Jun 27, 2020 at 12:19:45PM +0200, Yorhel <info at yorhel.nl> wrote:
> What I've observed is that it is possible to corrupt the internal state
> of AnyEvent's pure-perl event model by breaking out of a while loop over
> a filehandle, i.e. `while(<$FH>) { last }` is enough to cause havoc.

Yes, that's true, because that while statement will change $_, which is a
global variable also used by AnyEvent::Loop (and a lot of other code).

In general, in perl, when you modify global variables, you need to
localise them. e.g.

   local $_;
   while (<...>) {

You can additionally use AnyEvent::Strict (e.g. by putting AE_STRICT=1
into your environment, at least during development), which should catch
cases where your callback modifies such variables without restoring them
(and catches a lot of other usage bugs).

AnyEvent, by default, does not check callbacks and function invocations
for correctness (for speed), but you can enable a stricter checking mode
vias AnyEvent::Strict, which tries its best to detect problems independent
of the event model - otherwise code might often work with one event model,
but not another.

> perl 5.30.3 x86_64-linux with AnyEvent 7.17. The problem does not occur
> when the EV model is used. I suspect the problem also does not occur on
> earlier perl versions, seeing as someone else has gotten the exact same
> error message almost 3 years ago:

It will almost certainly occur on any perl version, as the behaviour of
while hasn't changed ever, as far as I know, and is one of those perl
traps: people seem to expect while (<>) to work like for (...), but it
doesn't.

> I'm a bit at a loss here. I'll try to report this at perl upstream
> if/when I manage to create a minimal example that exposes the bug
> without AnyEvent. Until then, using the EV model or writing the
> following instead will do as workaround:
> 
>   while(local $_ = <$FH>) {..}

This would actually be a fix, not a workaround - it's a bug to modify
$_ in your callbacks (as it would be a bug to modify many other global
variabes, such as $[).

It's lamentable that "while" doesn't local'ise $_, but I the train to
change that has left decades ago, so all you can do is cope with it.

-- 
                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_              http://www.deliantra.net
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      schmorp at schmorp.de
      -=====/_/_//_/\_,_/ /_/\_\



More information about the anyevent mailing list