[Twisted-Python] Re: [Twisted-commits] Today is screw with twisted's guts day.

Andrew Bennetts andrew-twisted at puzzling.org
Wed Nov 19 17:53:19 MST 2003


On Wed, Nov 19, 2003 at 02:07:39PM -0700, exarkun CVS wrote:
> Index: Twisted/twisted/internet/base.py
> diff -u Twisted/twisted/internet/base.py:1.67 Twisted/twisted/internet/base.py:1.68
> --- Twisted/twisted/internet/base.py:1.67	Fri Oct 24 12:45:58 2003
> +++ Twisted/twisted/internet/base.py	Wed Nov 19 14:07:38 2003
> @@ -400,12 +400,12 @@
>          """Run all pending timed calls.
>          """
>          if self.threadCallQueue:
> -            for i in range(len(self.threadCallQueue)):
> -                callable, args, kw = self.threadCallQueue.pop(0)
> +            for (f, a, kw) in self.threadCallQueue:
>                  try:
> -                    callable(*args, **kw)
> +                    f(*a, **kw)
>                  except:
> -                    log.deferr()
> +                    log.err()
> +            del self.threadCallQueue[:]
>          now = time()
>          while self._pendingTimedCalls and (self._pendingTimedCalls[-1].time <= now):
>              call = self._pendingTimedCalls.pop()

I think this change introduces a race condition.  It's possible for a thread
to call callFromThread between the end of the for loop and the del
statement.

(callFromThread is defined as:
    def callFromThread(self, f, *args, **kw):
        """See twisted.internet.interfaces.IReactorThreads.callFromThread.
        """
        assert callable(f), "%s is not callable" % f
        if threadable.isInIOThread():
            self.callLater(0, f, *args, **kw)
        else:
            # lists are thread-safe in CPython, but not in Jython
            # this is probably a bug in Jython, but until fixed this code
            # won't work in Jython.
            self.threadCallQueue.append((f, args, kw))
            self.wakeUp()
)

So I think it's possible to lose thread calls.  I *think* this patch will
fix it, but more eyeballs are always welcome with threaded code:

diff -u -r1.68 base.py
--- twisted/internet/base.py    19 Nov 2003 21:07:38 -0000      1.68
+++ twisted/internet/base.py    20 Nov 2003 00:52:08 -0000
@@ -400,12 +400,14 @@
         """Run all pending timed calls.
         """
         if self.threadCallQueue:
+            count = 0
             for (f, a, kw) in self.threadCallQueue:
                 try:
                     f(*a, **kw)
                 except:
                     log.err()
-            del self.threadCallQueue[:]
+                count += 1
+            del self.threadCallQueue[:count]
         now = time()
         while self._pendingTimedCalls and (self._pendingTimedCalls[-1].time <= now):
             call = self._pendingTimedCalls.pop()


-Andrew.





More information about the Twisted-Python mailing list