Opened 4 years ago

Last modified 4 years ago

#8313 defect new

twisted.names.client lookups fail with 'NoneType' object has no attribute 'stopListening'

Reported by: Alex Gaynor Owned by:
Priority: normal Milestone:
Component: names Keywords:
Cc: Branch:
Author:

Description

Traceback:

[Failure instance: Traceback: <type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'stopListening'
/Users/alex_gaynor/.virtualenvs/tempenv-3ec52995529ce/site-packages/twisted/internet/base.py:825:runUntilCurrent
/Users/alex_gaynor/.virtualenvs/tempenv-3ec52995529ce/site-packages/twisted/names/dns.py:2698:_clearFailed
/Users/alex_gaynor/.virtualenvs/tempenv-3ec52995529ce/site-packages/twisted/internet/defer.py:434:errback
/Users/alex_gaynor/.virtualenvs/tempenv-3ec52995529ce/site-packages/twisted/internet/defer.py:501:_startRunCallbacks
--- <exception caught here> ---
/Users/alex_gaynor/.virtualenvs/tempenv-3ec52995529ce/site-packages/twisted/internet/defer.py:588:_runCallbacks
/Users/alex_gaynor/.virtualenvs/tempenv-3ec52995529ce/site-packages/twisted/names/client.py:266:cbQueried
]

Code to reproduce:

from __future__ import print_function

import csv
import sys

from twisted.internet.defer import inlineCallbacks, DeferredList
from twisted.internet.task import react
from twisted.names import client


def has_spf_record(records):
    for record in records:
        for p in record.payload.data:
            if p.startswith("v=spf"):
                return True
    return False


@inlineCallbacks
def main(reactor, argv):
    domains = []
    with open("2016-01-19-federal.csv") as f:
        for row in csv.DictReader(f):
            domains.append(row["Domain Name"])

    mx_records = yield DeferredList([
        client.lookupMailExchange(domain)
        for domain in domains
    ], consumeErrors=True)

    domains_with_mx_records = []
    for domain, (success, result) in zip(domains, mx_records):
        if success:
            (records, _, _) = result
            if records:
                domains_with_mx_records.append(domain)
        else:
            print("Error:", domain, result)

    txt_records = yield DeferredList([
        client.lookupText(domain)
        for domain in domains_with_mx_records
    ], consumeErrors=True)

    domains_missing_spf = []
    for domain, (success, result) in zip(domains_with_mx_records, txt_records):
        if success:
            (records, _, _) = result
            if not has_spf_record(records):
                domains_missing_spf.append(domain)
        else:
            print("Error:", domain, result)

    print()
    print("Domains:", len(domains))
    print("With MX:", len(domains_with_mx_records))
    print("Missing:", len(domains_missing_spf))
    print(domains_missing_spf)


if __name__ == "__main__":
    react(main, sys.argv)

The input file can be obtained from: https://github.com/GSA/data/blob/gh-pages/dotgov-domains/2016-01-19-federal.csv

Change History (1)

comment:1 Changed 4 years ago by Alex Gaynor

It looks like the case this would occur in is if DNSDatagramProtocol.query encountered an exception in self.startListening().

Note: See TracTickets for help on using tickets.