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.