Yohann
Yohann

Reputation: 6346

Handle error on a simple DNS Twisted Client

The following DNS async client works fine if all domains exist.

However, if a domain name doesn't exist, the DNSNameError exception is raised and isn't not catched by my "try except" block. Then, the other domains are not resolve.

I have looking at the documentation of DNSNameError and defer but I didn't find how handle this error with addErrback because I use @inlineCallbacks.

Question : How catch the DNSNameError exception in query() ?

from itertools import cycle
from pprint import pprint
from twisted.names import client, dns
from twisted.internet.task import react
from twisted.internet import defer, reactor

def query(reactor, server, name):

    resolver = client.Resolver(
        resolv="/dev/null", servers=[(server, 53)], reactor=reactor)

    try:
        return resolver.lookupAddress(name)
    except:
        print "error query"
        return defer.returnValue(([],[],[]))


@defer.inlineCallbacks
def main(reactor, names):
    servers = ["4.2.2.1", "8.8.8.8"]

    next_server = cycle(servers).next

    results = []
    for n in names:
        try:
            results.append(query(reactor, next_server(), n))
        except:
            print "error append"


    try:
        results = yield defer.gatherResults(results)
        print "Success."
    except:
        print "Error result"
    finally:
        print "Shutting down"
        reactor.stop()

    pprint(zip(names, results))

if __name__ == '__main__':
    main(reactor, ('google.com', 'notexist.www','google.fr',))
    reactor.run()

Result:

$ipython twisteddns.py 
ipython twisteddns.py 
Error result
Shutting down
[('google.com', <Deferred at 0xad862ac>),
 ('notexist.www',
  <Deferred at 0xad8666c current result: <twisted.python.failure.Failure <class 'twisted.names.error.DNSNameError'>>>),
 ('google.fr', <Deferred at 0xad869ac>)]
Unhandled error in Deferred:
Unhandled Error
Traceback (most recent call last):
Failure: twisted.names.error.DNSNameError: <twisted.names.dns.Message instance at 0xad86a6c>

Upvotes: 0

Views: 970

Answers (1)

Jean-Paul Calderone
Jean-Paul Calderone

Reputation: 48335

First, never use returnValue outside of a function decorated with inlineCallbacks. It doesn't make any sense, it will produce surprising results, it'll trigger warnings telling you not to do it, and it'll probably break even worse than it is already broken in some future release of Twisted.

The function you're looking for in query is defer.succeed. As in:

...
except:
    print "error query"
    return defer.succeed(([],[],[]))

But since you're not using inlineCallbacks on query, you should add this as an errback instead.

d = resolver.lookupAddress(name)
def queryFailed(reason):
    log.err(reason, "Lookup of %s failed" % (name,))
    return ([], [], [])
d.addErrback(queryFailed)
return d

Upvotes: 1

Related Questions