Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AttributeError: 'GenericRdata' object has no attribute 'target' #59

Closed
arekm opened this issue Feb 26, 2014 · 13 comments
Closed

AttributeError: 'GenericRdata' object has no attribute 'target' #59

arekm opened this issue Feb 26, 2014 · 13 comments

Comments

@arekm
Copy link

arekm commented Feb 26, 2014

python-dns 1.11.1

Hit this once but not always reproducible. Unfortunately don't have data what domain was actually queried.

Exception in thread Thread-5:
Traceback (most recent call last):
File "/usr/share/python3.3/threading.py", line 901, in _bootstrap_inner
self.run()
File "/usr/share/python3.3/threading.py", line 858, in run
self._target(_self._args, *_self._kwargs)
File "report_unused_domains.py", line 241, in _tFilterByDns
new_domain_list, not_used_domain_list, nxdomains, nonameservers, noanswer = self.filterByDns([domain_data])
File "report_unused_domains.py", line 342, in filterByDns
resolver_answer = dns.resolver.query(domain_data['domain_name'], 'NS')
File "/usr/share/python3.3/site-packages/dns/resolver.py", line 972, in query
raise_on_no_answer, source_port)
File "/usr/share/python3.3/site-packages/dns/resolver.py", line 827, in query
source_port=source_port)
File "/usr/share/python3.3/site-packages/dns/query.py", line 230, in udp
one_rr_per_rrset=one_rr_per_rrset)
File "/usr/share/python3.3/site-packages/dns/message.py", line 787, in from_wire
reader.read()
File "/usr/share/python3.3/site-packages/dns/message.py", line 726, in read
self._get_section(self.message.answer, ancount)
File "/usr/share/python3.3/site-packages/dns/message.py", line 708, in _get_section
rrset.add(rd, ttl)
File "/usr/share/python3.3/site-packages/dns/rdataset.py", line 124, in add
super(Rdataset, self).add(rd)
File "/usr/share/python3.3/site-packages/dns/set.py", line 46, in add
if not item in self.items:
File "/usr/share/python3.3/site-packages/dns/rdata.py", line 218, in eq
return self._cmp(other) == 0
File "/usr/share/python3.3/site-packages/dns/rdtypes/nsbase.py", line 68, in _cmp
return dns.util.cmp(self.target, other.target)
AttributeError: 'GenericRdata' object has no attribute 'target'

@rthalley
Copy link
Owner

On Feb 26, 2014, at 6:28, Arkadiusz Miśkiewicz notifications@github.com wrote:

python-dns 1.11.1

Hit this once but not always reproducible. Unfortunately don't have data what domain was actually queried

Is this in a program that has been converted into an executable or is it just a normal script running on a system with dnspython installed in the usual way?

@arekm
Copy link
Author

arekm commented Feb 26, 2014

Normal script, running on linux x86_64 with python 3.3.4. The script does dns queries in multiple threads. The domain in question was diagnostyka-kardiologiczna.pl but simple NS querying in a loop doesn't trigger the problem. Some threading related issue maybe?

@rthalley
Copy link
Owner

On Feb 26, 2014, at 6:42, Arkadiusz Miśkiewicz notifications@github.com wrote:

Normal script, running on linux x86_64 with python 3.3.4. The script does dns queries in multiple threads. The domain in question was diagnostyka-kardiologiczna.pl but simple NS querying in a loop doesn't trigger the problem. Some threading related issue maybe?

Could be! The way I read the stack trace, we're trying to use the NS comparison code to compare an NS rdata and a generic rdata. But an NS rdata should never have become a GenericRdata because we have an NS class :)

dnspython dynamically loads such classes, and doesn't currently apply any locking when doing so, so I wonder if there's some race in the loading that leads to one thread getting an NS rdata and another erroneously falling into the "we don't have a special class for that" case.

A lock serializing dns/rdata.py's get_rdata_class() would probably fix it. Perhaps something like this:

diff --git a/dns/rdata.py b/dns/rdata.py
index 74ddef0..ab1e1e8 100644
--- a/dns/rdata.py
+++ b/dns/rdata.py
@@ -27,6 +27,10 @@ chunk of hexstring that _hexify() produces before whitespace occurs.

import base64
import io
+try:

  • import threading as _threading
    +except ImportError:
  • import dummy_threading as _threading

import dns.exception
import dns.name
@@ -367,6 +371,7 @@ class GenericRdata(Rdata):

_rdata_modules = {}
_module_prefix = 'dns.rdtypes'
+_get_rdata_class_lock = _threading.Lock()

def get_rdata_class(rdclass, rdtype):

@@ -377,29 +382,30 @@ def get_rdata_class(rdclass, rdtype):
mod = getattr(mod, comp)
return mod

  • mod = _rdata_modules.get((rdclass, rdtype))

  • rdclass_text = dns.rdataclass.to_text(rdclass)

  • rdtype_text = dns.rdatatype.to_text(rdtype)

  • rdtype_text = rdtype_text.replace('-', '_')

  • if not mod:

  •    mod = _rdata_modules.get((dns.rdatatype.ANY, rdtype))
    
  • with _get_rdata_class_lock:

  •    mod = _rdata_modules.get((rdclass, rdtype))
    
  •    rdclass_text = dns.rdataclass.to_text(rdclass)
    
  •    rdtype_text = dns.rdatatype.to_text(rdtype)
    
  •    rdtype_text = rdtype_text.replace('-', '_')
     if not mod:
    
  •        try:
    
  •            mod = import_module('.'.join([_module_prefix,
    
  •                                          rdclass_text, rdtype_text]))
    
  •            _rdata_modules[(rdclass, rdtype)] = mod
    
  •        except ImportError:
    
  •        mod = _rdata_modules.get((dns.rdatatype.ANY, rdtype))
    
  •        if not mod:
             try:
                 mod = import_module('.'.join([_module_prefix,
    
  •                                              'ANY', rdtype_text]))
    
  •                _rdata_modules[(dns.rdataclass.ANY, rdtype)] = mod
    
  •                                              rdclass_text, rdtype_text]))
    
  •                _rdata_modules[(rdclass, rdtype)] = mod
             except ImportError:
    
  •                mod = None
    
  • if mod:

  •    cls = getattr(mod, rdtype_text)
    
  • else:

  •    cls = GenericRdata
    
  • return cls

  •                try:
    
  •                    mod = import_module('.'.join([_module_prefix,
    
  •                                                  'ANY', rdtype_text]))
    
  •                    _rdata_modules[(dns.rdataclass.ANY, rdtype)] = mod
    
  •                except ImportError:
    
  •                    mod = None
    
  •    if mod:
    
  •        cls = getattr(mod, rdtype_text)
    
  •    else:
    
  •        cls = GenericRdata
    
  •    return cls
    

    def from_text(rdclass, rdtype, tok, origin = None, relativize = True):
    """Build an rdata object from text format.

@arekm
Copy link
Author

arekm commented Feb 27, 2014

Looks like that locking fix works. Previously our production script died in ~10minutes. With this patch no problem for over a hour.

@rthalley
Copy link
Owner

On Feb 27, 2014, at 1:55, Arkadiusz Miśkiewicz notifications@github.com wrote:

Looks like that locking fix works. Previously our production script died in ~10minutes. With this patch no problem for over a hour.

Glad to hear that! I'll commit the patch soon then, so it will be in the next release. Thanks for testing it!

/Bob

@underrun
Copy link

i have to say i think having threadlocal resolvers would be a better option than adding locks everywhere.

@rthalley
Copy link
Owner

On Feb 27, 2014, at 15:25, Derek Wilson notifications@github.com wrote:

i have to say i think having threadlocal resolvers would be a better option than adding locks everywhere

Doesn't help when all the threads are sharing the dynamic rdatatype loading mechanism.

@arekm
Copy link
Author

arekm commented Feb 28, 2014

Is this rdatatype dynamic loading a feature? I mean feature exposed to user, or just internal implementation. If only internal implementation then maybe it doesn't make big sense to do that.

@underrun
Copy link

it seems to me that it would make more sense, rather than updating a global dict of rdata modules, to load the dict upfront and then shared access is all reads (no locking required).

@rthalley rthalley added this to the 1.12 milestone Jun 21, 2014
@rthalley rthalley closed this as completed May 8, 2016
@hirios
Copy link

hirios commented Apr 6, 2021

I am experiencing this same problem when I try to compile a program that uses pymongo and dnspython. I'm trying to compile with nuitka. This is output:

client = MongoClient("mongodb+srv://exemplooooo___exempleeeee/<dbname>?retryWrites=true&w=majority")
  File "C:\Users\Novo\AppData\Local\Temp\ONEFIL~1\pymongo\mongo_client.py", line 639, in __init__
  File "C:\Users\Novo\AppData\Local\Temp\ONEFIL~1\pymongo\uri_parser.py", line 500, in parse_uri
  File "C:\Users\Novo\AppData\Local\Temp\ONEFIL~1\pymongo\srv_resolver.py", line 102, in get_hosts
  File "C:\Users\Novo\AppData\Local\Temp\ONEFIL~1\pymongo\srv_resolver.py", line 86, in _get_srv_response_and_hosts
  File "C:\Users\Novo\AppData\Local\Temp\ONEFIL~1\pymongo\srv_resolver.py", line 87, in <listcomp>
AttributeError: 'GenericRdata' object has no attribute 'target'```

@bwelling
Copy link
Collaborator

bwelling commented Apr 6, 2021

This error is related to building dnspython with nuitka, not dnspython itself, and not related to the original report in this ticket. It appears that passing --include-package=dns to the nuitka builder will deal with the dynamic loading issue.

@AadeshKabra
Copy link

Screenshot 2023-06-23 190930
I am trying to convert a flask application into an executable. The .exe file is getting generated. But on opening the file I get this error on cmd.
The error occurs particularly on the following line:
mongo_client = pymongo.MongoClient("mongodb+srv://xyz:xyz@cluster0.gwnjuq6.mongodb.net/?retryWrites=true&w=majority", maxPoolSize=50, connect=False)
How do I solve it?

@rthalley
Copy link
Owner

You need to either have whatever is converting the application into an executable include all of dnspython's files, or you need to explicit include all the needed types. E.g. in this case add

import dns.rdtypes.IN.SRV

I expect you might need

import dns.rdtypes.IN.A
import dns.rdtypes.IN.AAAA

too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants