Ticket #5962: callLater-5962-v1.patch

File callLater-5962-v1.patch, 2.6 KB (added by Michael Grazebrook, 8 years ago)
  • twisted/internet/task.py

    diff --git twisted/internet/task.py twisted/internet/task.py
    index f1984f7..314bd6f 100644
    class Clock: 
    786786        """
    787787        self.rightNow += amount
    788788        self._sortCalls()
    789         while self.calls and self.calls[0].getTime() <= self.seconds():
    790             call = self.calls.pop(0)
     789        calls = self.calls
     790        self.calls = []
     791        while calls:
     792            call = calls.pop(0)
     793            if call.getTime() > self.seconds():
     794                continue
     795
    791796            call.called = 1
     797            # See ticket #6867 : call.func needs to handle exceptions.
     798            # An exception puts self.calls in an invalid state
    792799            call.func(*call.args, **call.kw)
    793             self._sortCalls()
     800        self.calls.extend(calls)
    794801
    795802
    796803    def pump(self, timings):
  • twisted/test/test_task.py

    diff --git twisted/test/test_task.py twisted/test/test_task.py
    index e28ce92..ad5568e 100644
    class ClockTestCase(unittest.TestCase): 
    9090        self.failIf(call.active())
    9191
    9292
     93    def _advanceCallingCallLater(self, advanceBy):
     94        """
     95        Adds a C{callLater} for immediate execution and advances the clock
     96        by C{advanceBy} seconds.
     97
     98        @type advanceBy: number
     99        @param advanceBy: Seconds to advance by.
     100
     101        @rtype: C{int}
     102        @return: Number of times C{f} is called.
     103        """
     104        i = [0]
     105        def f():
     106            if i[0] < 6:
     107                c.callLater(0, f)
     108            i[0] += 1
     109        c = task.Clock()
     110        f()
     111        c.advance(advanceBy)
     112        return i[0]
     113
     114
     115        def testAdvanceCallLaterZero(self):
     116            """
     117            C{f} calling C{Clock.callLater(0, f)} does not create an infinite loop
     118            """
     119            self.assertEqual(self._advanceCallingCallLater(0), 2)
     120
     121
     122    def testAdvanceCallLaterZeroAdvanceOne(self):
     123        """
     124        Same as testAdvanceCallLaterZero in practice.
     125        This test is included because it catches a bug in original proposed fix.
     126        """
     127        self.assertEqual(self._advanceCallingCallLater(1), 2)
     128
     129
    93130    def testAdvanceCancel(self):
    94131        """
    95132        Test attemping to cancel the call in a callback.
  • new file twisted/topfiles/5962.bugfix

    diff --git twisted/topfiles/5962.bugfix twisted/topfiles/5962.bugfix
    new file mode 100644
    index 0000000..1146864
    - +  
     1twisted.internet.task.advance now avoids running any callbacks which are added during its excecution, which prevents a possible infinite loop.
     2