Issue #12 resolved

execute_every with a period of 0 causes infinite loop

Jason R. Coombs
repo owner created an issue

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).

Comments (2)

  1. Jason R. Coombs reporter

    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.

  2. Log in to comment