title: How can I catch asyncio.exceptions.InvalidStateError from dns.asyncresolver.Resolver?
body: <p>I'm running a load of DNS lookups through dns.asyncresolver and around 0.05% of them are throwing:</p>
  <pre><code>Exception in callback _SelectorDatagramTransport._read_ready()
  handle: &lt;Handle _SelectorDatagramTransport._read_ready()&gt;
  Traceback (most recent call last):
    File &quot;/usr/lib/python3.8/asyncio/events.py&quot;, line 81, in _run
      self._context.run(self._callback, *self._args)
    File &quot;/usr/lib/python3.8/asyncio/selector_events.py&quot;, line 1021, in _read_ready
      self._protocol.datagram_received(data, addr)
    File &quot;/usr/local/lib/python3.8/dist-packages/dns/_asyncio_backend.py&quot;, line 30, in datagram_received
      self.recvfrom.set_result((data, addr))
  asyncio.exceptions.InvalidStateError: invalid state
  </code></pre>
  <p>If I edit /usr/local/lib/python3.8/dist-packages/dns/_asyncio_backend.py from:</p>
  <pre><code>    def datagram_received(self, data, addr):
          if self.recvfrom:
              self.recvfrom.set_result((data, addr))
              self.recvfrom = None
  </code></pre>
  <p>To:</p>
  <pre><code>    def datagram_received(self, data, addr):
          if self.recvfrom:
              try:
                  self.recvfrom.set_result((data, addr))
              except Exception as e:
                  print(self.recvfrom)
              self.recvfrom = None
  </code></pre>
  <p>I instead get:</p>
  <pre><code># python3 asynctest.py
  &lt;Future cancelled&gt;
  &lt;Future cancelled&gt;
  &lt;Future cancelled&gt;
  </code></pre>
  <p>Is there any way I can catch this without editing Python library files, which I'd really rather not do?</p>
  <p>Test code below:</p>
  <pre><code>from dns.asyncresolver import Resolver
  import asyncio
  import sqlite3
   
  async def getIPs():
      conn = sqlite3.connect('hosts.db')
      c    = conn.cursor()
      c.execute('SELECT DISTINCT job.host FROM job')
      # sqlite&gt; SELECT DISTINCT job.host FROM job LIMIT 10;
      # .
      # 163mx00.mxmail.netease.com.
      # 163mx01.mxmail.netease.com.
      # 163mx02.mxmail.netease.com.
      # 163mx03.mxmail.netease.com.
      # a.dailymotion.com.
      # a.iana-servers.net.
      # a.icann-servers.net.
      # a.mx.openstreetmap.org.
      # a.ns.apple.com.
      # Total: 10,259
      lookups = c.fetchall()
      res = Resolver()
      sema = asyncio.Semaphore(500)
      output = [get_ips(domain[0], res, sema) for domain in lookups]
      await asyncio.gather(*output, return_exceptions=False)
   
  async def get_ips(domain, res, sema):
      async with sema:
          try:
              ip = await res.resolve(domain, 'A')
              for result in ip:
                  result = result.to_text()
                  break
          except Exception as e:
              pass
          try:
              ip = await res.resolve(domain, 'AAAA')
              for result in ip:
                  result = result.to_text()
                  break
          except Exception as e:
              pass
   
  asyncio.run(getIPs())
  </code></pre>