[Twisted-Python] Unhandled error in Deferred with twisted-8.2.0, but not with twisted-2.1.0

Am currently trying to upgrade to twisted-8.2.0. For some reason, twisted-8.2.0 thinks my deferred below was gc'd with an unhandled error, and tells me about it upon reactor exit. With python-2.4.2/twisted-2.1.0, no issues. With python-2.6.1/twisted-8.2.0, I see these issues. Any ideas why? Thanks. $ cat ./deferred-errors.py #!/usr/bin/env python import datetime, logging, os, random, re, shutil, socket import subprocess, sys, tempfile, threading, time, traceback from twisted.internet import reactor from twisted.internet import defer from twisted.internet.utils import getProcessOutput from twisted.python import log import twisted print 'twisted version is', twisted.__version__ def foo(): d = getProcessOutput('/bin/hostnameX') def cb(result): print 'cb: %s' % (result) def eb(failure): print 'eb caught the failure!' d.addCallback(cb) d.addErrback(eb) reactor.callWhenRunning(foo) reactor.callLater(3, reactor.stop) reactor.run() $ /sw/external/python-2.4.2/bin/python ./deferred-errors.py twisted version is 2.1.0 eb caught the failure! $ /sw/external/python-2.6.1/bin/python ./deferred-errors.py twisted version is 8.2.0 eb caught the failure! Unhandled error in Deferred: Traceback (most recent call last): Failure: twisted.internet.error.ProcessTerminated: A process has ended with a probable error condition: process ended with exit code 1.

On 04:33 pm, benjamin.rutt@gs.com wrote:
A second Deferred is created during getProcessOutput to track the ending of the process as distinct from the end of its output. You have to catch that exception as well if you don't want any exceptions logged. Arguably, this is a bug, since it changes the behavior and complicates error handling; if you think so, feel free to file a ticket on the tracker. I just learned about this behavior myself, in the process of tracking down your question :). This behavior was changed in: http://twistedmatrix.com/trac/changeset/24810 as part of a fix for: http://twistedmatrix.com/trac/ticket/3239 and that took place after 8.1 but before 8.2. In the meanwhile, you could upgrade to 8.2 before going to 8.2 to avoid this issue; going from 8.1 to 8.2 should be significantly easier than going from 2.1 to 8.1 ;). If you'd still like to upgrade all the way, here's a "correct" version of your program (with spurious imports removed), according to the behavior in 8.2.0: #!/usr/bin/env python from twisted.internet import reactor from twisted.internet.utils import getProcessOutput def foo(): d = getProcessOutput('/some/non/existent/program') def cb(result): print 'cb: %s' % (result) def eb(failure): failure.trap(IOError) def endedException(ended): print 'really, caught it!' failure.value.processEnded.addErrback(endedException) print 'eb caught the failure!' d.addCallback(cb) d.addErrback(eb) def stopit(): print 'Stopping reactor.' reactor.stop() print 'Stopped.' reactor.callWhenRunning(foo) reactor.callLater(1.0, stopit) reactor.run()

Thank you for digging this up - I filed a bug. http://twistedmatrix.com/trac/ticket/3892 -----Original Message----- From: twisted-python-bounces@twistedmatrix.com [mailto:twisted-python-bounces@twistedmatrix.com] On Behalf Of glyph@divmod.com Sent: Friday, June 26, 2009 1:49 PM To: Twisted general discussion Subject: Re: [Twisted-Python] Unhandled error in Deferred with twisted-8.2.0,but not with twisted-2.1.0 On 04:33 pm, benjamin.rutt@gs.com wrote:
A second Deferred is created during getProcessOutput to track the ending of the process as distinct from the end of its output. You have to catch that exception as well if you don't want any exceptions logged. Arguably, this is a bug, since it changes the behavior and complicates error handling; if you think so, feel free to file a ticket on the tracker. I just learned about this behavior myself, in the process of tracking down your question :). This behavior was changed in: http://twistedmatrix.com/trac/changeset/24810 as part of a fix for: http://twistedmatrix.com/trac/ticket/3239 and that took place after 8.1 but before 8.2. In the meanwhile, you could upgrade to 8.2 before going to 8.2 to avoid this issue; going from 8.1 to 8.2 should be significantly easier than going from 2.1 to 8.1 ;). If you'd still like to upgrade all the way, here's a "correct" version of your program (with spurious imports removed), according to the behavior in 8.2.0: #!/usr/bin/env python from twisted.internet import reactor from twisted.internet.utils import getProcessOutput def foo(): d = getProcessOutput('/some/non/existent/program') def cb(result): print 'cb: %s' % (result) def eb(failure): failure.trap(IOError) def endedException(ended): print 'really, caught it!' failure.value.processEnded.addErrback(endedException) print 'eb caught the failure!' d.addCallback(cb) d.addErrback(eb) def stopit(): print 'Stopping reactor.' reactor.stop() print 'Stopped.' reactor.callWhenRunning(foo) reactor.callLater(1.0, stopit) reactor.run() _______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

On 04:33 pm, benjamin.rutt@gs.com wrote:
A second Deferred is created during getProcessOutput to track the ending of the process as distinct from the end of its output. You have to catch that exception as well if you don't want any exceptions logged. Arguably, this is a bug, since it changes the behavior and complicates error handling; if you think so, feel free to file a ticket on the tracker. I just learned about this behavior myself, in the process of tracking down your question :). This behavior was changed in: http://twistedmatrix.com/trac/changeset/24810 as part of a fix for: http://twistedmatrix.com/trac/ticket/3239 and that took place after 8.1 but before 8.2. In the meanwhile, you could upgrade to 8.2 before going to 8.2 to avoid this issue; going from 8.1 to 8.2 should be significantly easier than going from 2.1 to 8.1 ;). If you'd still like to upgrade all the way, here's a "correct" version of your program (with spurious imports removed), according to the behavior in 8.2.0: #!/usr/bin/env python from twisted.internet import reactor from twisted.internet.utils import getProcessOutput def foo(): d = getProcessOutput('/some/non/existent/program') def cb(result): print 'cb: %s' % (result) def eb(failure): failure.trap(IOError) def endedException(ended): print 'really, caught it!' failure.value.processEnded.addErrback(endedException) print 'eb caught the failure!' d.addCallback(cb) d.addErrback(eb) def stopit(): print 'Stopping reactor.' reactor.stop() print 'Stopped.' reactor.callWhenRunning(foo) reactor.callLater(1.0, stopit) reactor.run()

Thank you for digging this up - I filed a bug. http://twistedmatrix.com/trac/ticket/3892 -----Original Message----- From: twisted-python-bounces@twistedmatrix.com [mailto:twisted-python-bounces@twistedmatrix.com] On Behalf Of glyph@divmod.com Sent: Friday, June 26, 2009 1:49 PM To: Twisted general discussion Subject: Re: [Twisted-Python] Unhandled error in Deferred with twisted-8.2.0,but not with twisted-2.1.0 On 04:33 pm, benjamin.rutt@gs.com wrote:
A second Deferred is created during getProcessOutput to track the ending of the process as distinct from the end of its output. You have to catch that exception as well if you don't want any exceptions logged. Arguably, this is a bug, since it changes the behavior and complicates error handling; if you think so, feel free to file a ticket on the tracker. I just learned about this behavior myself, in the process of tracking down your question :). This behavior was changed in: http://twistedmatrix.com/trac/changeset/24810 as part of a fix for: http://twistedmatrix.com/trac/ticket/3239 and that took place after 8.1 but before 8.2. In the meanwhile, you could upgrade to 8.2 before going to 8.2 to avoid this issue; going from 8.1 to 8.2 should be significantly easier than going from 2.1 to 8.1 ;). If you'd still like to upgrade all the way, here's a "correct" version of your program (with spurious imports removed), according to the behavior in 8.2.0: #!/usr/bin/env python from twisted.internet import reactor from twisted.internet.utils import getProcessOutput def foo(): d = getProcessOutput('/some/non/existent/program') def cb(result): print 'cb: %s' % (result) def eb(failure): failure.trap(IOError) def endedException(ended): print 'really, caught it!' failure.value.processEnded.addErrback(endedException) print 'eb caught the failure!' d.addCallback(cb) d.addErrback(eb) def stopit(): print 'Stopping reactor.' reactor.stop() print 'Stopped.' reactor.callWhenRunning(foo) reactor.callLater(1.0, stopit) reactor.run() _______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
participants (2)
-
glyph@divmod.com
-
Rutt, Benjamin