jaraco / irc

Full-featured Python IRC library for Python.
MIT License
392 stars 87 forks source link

execute_every with a period of 0 causes infinite loop #12

Closed jaraco closed 8 years ago

jaraco commented 8 years ago

Looking at process_timeout, the code looks like this:

            while self.delayed_commands:
                command = self.delayed_commands[0]
                if not command.due():
                    break
                command.function(*command.arguments)
                if isinstance(command, PeriodicCommand):
                    self._schedule_command(command.next())
                del self.delayed_commands[0]

If one of the delayed_commands is a PeriodicCommand with delay of 0 (as created by execute_every with period of 0), the _schedule_command will always re-add the command immediately after running it, and it will satisfy the command.due() on the subsequent iteration, causing an infinite loop.

At the very least, the IRC client should raise an error if one attempts to create such a command. Even better would be to support periodic commands with a delay of 0 (which one would want to run every timeout, but only once per).


jaraco commented 8 years ago

After looking into this a bit more, I see it's even more complicated by the fact that there isn't necessarily an idle timeout. If the client is running under an external event loop, and fn_to_add_timeout is supplied, it's conceivable that even if the new command is scheduled late in process_timeout (outside of the while loop), it will still cause a tight loop, triggering the timeout immediately from the external event loop.

Therefore, I believe the proper fix is to simply disallow a delay of 0 for periodic commands.


Original comment by: Jason R. Coombs

jaraco commented 8 years ago

PeriodicCommand now raises a ValueError if created with a negative or zero delay. Fixes #12

→ <>


Original comment by: Jason R. Coombs