URI: 
       tMerge pull request #4486 from SomberNight/getaddrinfo_take2 - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 2693d345f9c63b9f14000e80b0be13b09a809f5d
   DIR parent 402b49e76b9360edf6dc0af0bd30e2126f815f8e
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Mon,  2 Jul 2018 08:14:31 +0200
       
       Merge pull request #4486 from SomberNight/getaddrinfo_take2
       
       socket.getaddrinfo on win32: do our own dns resolution
       Diffstat:
         M lib/network.py                      |      42 ++++++++++++++++++++++++++++++-
       
       1 file changed, 41 insertions(+), 1 deletion(-)
       ---
   DIR diff --git a/lib/network.py b/lib/network.py
       t@@ -31,9 +31,15 @@ from collections import defaultdict
        import threading
        import socket
        import json
       +import sys
       +import ipaddress
        
       +import dns
       +import dns.resolver
        import socks
       +
        from . import util
       +from .util import print_error
        from . import bitcoin
        from .bitcoin import COIN
        from . import constants
       t@@ -444,7 +450,41 @@ class Network(util.DaemonThread):
                    socket.getaddrinfo = lambda *args: [(socket.AF_INET, socket.SOCK_STREAM, 6, '', (args[0], args[1]))]
                else:
                    socket.socket = socket._socketobject
       -            socket.getaddrinfo = socket._getaddrinfo
       +            if sys.platform == 'win32':
       +                # 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
       +            else:
       +                socket.getaddrinfo = socket._getaddrinfo
       +
       +    @staticmethod
       +    def _fast_getaddrinfo(host, *args, **kwargs):
       +        def needs_dns_resolving(host2):
       +            try:
       +                ipaddress.ip_address(host2)
       +                return False  # already valid IP
       +            except ValueError:
       +                pass  # not an IP
       +            if str(host) in ('localhost', 'localhost.',):
       +                return False
       +            return True
       +        try:
       +            if needs_dns_resolving(host):
       +                answers = dns.resolver.query(host)
       +                addr = str(answers[0])
       +            else:
       +                addr = host
       +        except dns.exception.DNSException:
       +            # dns failed for some reason, e.g. dns.resolver.NXDOMAIN
       +            # this is normal. Simply report back failure:
       +            raise socket.gaierror(11001, 'getaddrinfo failed')
       +        except BaseException as e:
       +            # Possibly internal error in dnspython :( see #4483
       +            # Fall back to original socket.getaddrinfo to resolve dns.
       +            print_error('dnspython failed to resolve dns with error:', e)
       +            addr = host
       +        return socket._getaddrinfo(addr, *args, **kwargs)
        
            @with_interface_lock
            def start_network(self, protocol, proxy):