URI: 
       tdns hacks on windows: resolve A and AAAA records in parallel - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit cb88a3b6e45e1261d4926d6d385f8f779a84a2d9
   DIR parent a5cd34dc089698ace69d43b3c3f54ffa0f70e18d
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Wed,  1 Jan 2020 07:00:16 +0100
       
       dns hacks on windows: resolve A and AAAA records in parallel
       
       Diffstat:
         M electrum/network.py                 |      20 ++++++++++++++------
       
       1 file changed, 14 insertions(+), 6 deletions(-)
       ---
   DIR diff --git a/electrum/network.py b/electrum/network.py
       t@@ -228,6 +228,8 @@ class UntrustedServerReturnedError(NetworkException):
                return f"<UntrustedServerReturnedError original_exception: {repr(self.original_exception)}>"
        
        
       +_dns_threads_executor = None  # type: Optional[concurrent.futures.Executor]
       +
        _INSTANCE = None
        
        
       t@@ -567,10 +569,13 @@ class Network(Logger):
                        # On Windows, socket.getaddrinfo takes a mutex, and might hold it for up to 10 seconds
                        # when dns-resolving. To speed it up drastically, we resolve dns ourselves, outside that lock.
                        # see #4421
       -                socket.getaddrinfo = self._fast_getaddrinfo
                        resolver = dns.resolver.get_default_resolver()
                        if resolver.cache is None:
                            resolver.cache = dns.resolver.Cache()
       +                global _dns_threads_executor
       +                if _dns_threads_executor is None:
       +                    _dns_threads_executor = concurrent.futures.ThreadPoolExecutor(max_workers=20)
       +                socket.getaddrinfo = self._fast_getaddrinfo
                    else:
                        socket.getaddrinfo = socket._getaddrinfo
                self.trigger_callback('proxy_set', self.proxy)
       t@@ -588,20 +593,23 @@ class Network(Logger):
                    return True
                def resolve_with_dnspython(host):
                    addrs = []
       -            expected_dnspython_errors = (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer)
       +            expected_errors = (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer,
       +                               concurrent.futures.CancelledError, concurrent.futures.TimeoutError)
       +            ipv6_fut = _dns_threads_executor.submit(dns.resolver.query, host, dns.rdatatype.AAAA)
       +            ipv4_fut = _dns_threads_executor.submit(dns.resolver.query, host, dns.rdatatype.A)
                    # try IPv6
                    try:
       -                answers = dns.resolver.query(host, dns.rdatatype.AAAA)
       +                answers = ipv6_fut.result()
                        addrs += [str(answer) for answer in answers]
       -            except expected_dnspython_errors as e:
       +            except expected_errors as e:
                        pass
                    except BaseException as e:
                        _logger.info(f'dnspython failed to resolve dns (AAAA) for {repr(host)} with error: {repr(e)}')
                    # try IPv4
                    try:
       -                answers = dns.resolver.query(host, dns.rdatatype.A)
       +                answers = ipv4_fut.result()
                        addrs += [str(answer) for answer in answers]
       -            except expected_dnspython_errors as e:
       +            except expected_errors as e:
                        # dns failed for some reason, e.g. dns.resolver.NXDOMAIN this is normal.
                        # Simply report back failure; except if we already have some results.
                        if not addrs: