Skip Menu |

This queue is for tickets about the AnyEvent CPAN distribution.

Report information
The Basics
Id: 117054
Status: open
Priority: 0/
Queue: AnyEvent

People
Owner: Nobody in particular
Requestors: zbbentley [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: In pure-perl loop, IO events can be indefinitely starved by always-ready timers
Date: Thu, 18 Aug 2016 17:07:27 -0400
To: bug-AnyEvent [...] rt.cpan.org
From: Zac Bentley <zbbentley [...] gmail.com>
In the pure-perl AnyEvent::Loop, there's a starvation condition that can occur if timer callbacks block for long enough that another timer is always ready when they finish. A full description and proposed solution are below. Sample code and a bad workaround are available on this stackoverflow question: http://stackoverflow.com/questions/37769891/why-wont-anyeventchild-callbacks-ever-run-if-interval-timer-events-are-always/37845061#37845061 Simple outline of the issue: Setup: Use the pure perl backend on a POSIX OS (reproduced on OSX and RHEL6) with Time::HiRes, without Async::Interrupt, without AIO. Much of that is probably unnecessary; that's just my setup. Steps to reproduce: 1. Schedule an interval timer event immediately, and then every N seconds where N>0. 2. Set the timer's callback to block (do something synchronous that cannot be interrupted by a signal, e.g. busy wait or use sigblock(2)) for M seconds, where M>N. 3. Set a signal watcher (really just a wrapped IO event) for any catchable signal S. 4. Run the event loop. 5. Wait some amount of time and then externally deliver signal S to the running process. Expected behavior: Interval callback fires once, and then continues firing roughly every M seconds (though it wants to run every N). When signal is delivered, signal watcher callback runs either immediately after the currently-executing interval callback, or after the immediately following execution of that same callback. Actual behavior: Interval callback fires once, and then continues firing roughly every M seconds (though it wants to run every N). Signal callback is never delivered. Suspected issue: AnyEvent::Loop::one_event finds and runs timer events. If no timer events are ready, it polls for IO events, and if none of either are ready, it runs idle events. The if/else behavior between timers and IO events should be removed: both sets of events should populate an internal queue, which should be drained before re-polling. Basically, the current logic should go from this: 1. Check for timer events, if any are found run them. 2. Else, select() for IO events, with a timeout of the time until the next timer, and if any are found run them 3. Else, run idle events if any. ...to this: 1. If there are events in @queue, pop one from the head and run it. 2. Else a. Check for timer events and add them to the tail of @queue. b. Select() for IO events and add them to the tail of @queue. This should be run uncondtionally. The timeout for select() should be: scalar(@queue) ? 0 : $wait, where $wait is the existing "time until next timer" value. c. If there are events in @queue, pop one from the head and run it. d. Else, run idle events if any. This can be implemented without consuming any additional memory. However, this adds overhead to one_event(). Select()s will be run more frequently: they will now be run whenever timers are due. I think that tradeoff is valid, since it ensures that all events will eventually be processed in roughly the order they "occur" (in concept), regardless of how much blocking time is spent outside of the event loop. I am not sure how other event loop implementations deal with issues like this. I know that many browser event loops use a backing queue like the one proposed above, but am not familiar with others. Unless all of the other AnyEvent backends mimic this behavior exactly, though (in such a way that fixing this issue would make the pure-perl loop the only deviant), fixing this still seems useful. Thanks! Zac
Subject: Re: [rt.cpan.org #117054] In pure-perl loop, IO events can be indefinitely starved by always-ready timers
Date: Sat, 20 Aug 2016 10:41:15 +0200
To: Zac Bentley via RT <bug-AnyEvent [...] rt.cpan.org>
From: Marc Lehmann <schmorp [...] schmorp.de>
Hi! Please send your bug report to the official contact/author address for the module in question (or send it to rt.cpan.org@schmorp.de, that's fine as well). What follows is the rationale for this request, you don't have to read it if you don't care. Why is this necessary? rt.cpan.org has many deficiencies which makes it tedious and hard to use, increasing the workload on the people who provide all the perl modules you probably appreciate (and that is really to be avoided - module authors should be able to invest all their time into improving their modules and not fighting with rt.cpan.org's bugs). Still, for some people, rt.cpan.org is useful to have, and some people even like it and really want to use it. That is fine, too. Unfortunately, the designers of rt.cpan.org didn't make their "service" optional - you can neither opt-in nor opt-out of rt.cpan.org as a module author. Just like a spammer, rt.cpan.org forces its "service" (whether wanted or unwanted) on everybody. Just like a spammer, they don't care for the people they actively hurt. Just like a spammer, they don't don't care to fix these issues and make their "service" ethically acceptable. You cannot even configure it to redirect tickets to somewhere else. Unfortunately, ignoring rt.cpan.org is not an option either: for people reporting possible bugs there is no indication that their report will be ignored, and for module authors it means they miss potentially vital bug reports such as yours (and of course it's a great impression if rt.cpan.org has lots of bug reports that are unanswered, making a module look unmaintained when in fact the opposite might be true). I am sorry that this wasted a bit of your time, but please understand that I am just as much a victim as you are - the problem is the unethical stance of the rt.cpan.org providers who force their "service" on everybody. Please redirect your bug report as stated in the beginning of this mail, and please consider petitioning the rt.cpan.org providers to stop their unethical behaviour and allow opt-in, opt-out, or some redirect option. One last issue: many people mail me that this can be "fixed" by including the bugtracker element in my module meta file. This is not true: 1. This field only affects search.cpan.org and maybe similar services. (Many people confuse rt.cpan.org with search.cpan.org for some reason). 2. It doesn't even work (there are still links to rt.cpan.org displayed). 3. Even if search.cpan.org does no longer display the link, it doesn't actually affect rt.cpan.org (and tests have shown that people go to rt.cpan.org regardless) Even *iff* rt.cpan.org would start listening on the bugtracker field, however, it's still wrong. I have a lot of modules, and each time a service like rt.cpan.org comes out, I would have to make dummy releases for all my modules. This not only creates a lot of extra work for me (I take releases very seriously) but also users, who would wonder why there is a new release. Thanks a lot, Marc Lehmann <rt.cpan.org@schmorp.de> Last updated: 2012-04-22