from tornado.concurrent import dummy_executor, run_on_executor
from tornado.ioloop import IOLoop
from tornado.platform.auto import set_close_exec
-from tornado.util import Configurable
+from tornado.util import u, Configurable
if hasattr(ssl, 'match_hostname') and hasattr(ssl, 'CertificateError'): # python 3.2+
ssl_match_hostname = ssl.match_hostname
ssl_match_hostname = backports.ssl_match_hostname.match_hostname
SSLCertificateError = backports.ssl_match_hostname.CertificateError
+# ThreadedResolver runs getaddrinfo on a thread. If the hostname is unicode,
+# getaddrinfo attempts to import encodings.idna. If this is done at
+# module-import time, the import lock is already held by the main thread,
+# leading to deadlock. Avoid it by caching the idna encoder on the main
+# thread now.
+u('foo').encode('idna')
+
+
def bind_sockets(port, address=None, family=socket.AF_UNSPEC, backlog=128, flags=None):
"""Creates listening sockets bound to the given port and address.
from __future__ import absolute_import, division, print_function, with_statement
import socket
+from subprocess import Popen
+import sys
+import time
from tornado.netutil import BlockingResolver, ThreadedResolver, is_valid_ip
from tornado.testing import AsyncTestCase, gen_test
super(ThreadedResolverTest, self).tearDown()
+@unittest.skipIf(futures is None, "futures module not present")
+class ThreadedResolverImportTest(unittest.TestCase):
+ def test_import(self):
+ # Test for a deadlock when importing a module that runs the
+ # ThreadedResolver at import-time. See resolve_test.py for
+ # full explanation.
+ command = [
+ sys.executable,
+ '-c',
+ 'import tornado.test.resolve_test']
+
+ start = time.time()
+ popen = Popen(command)
+ while time.time() - start < 20:
+ return_code = popen.poll()
+ if return_code is not None:
+ self.assertEqual(0, return_code)
+ return # Success.
+
+ self.fail("import timed out")
+
+
@unittest.skipIf(pycares is None, "pycares module not present")
class CaresResolverTest(AsyncTestCase, _ResolverTestMixin):
def setUp(self):
--- /dev/null
+from tornado.ioloop import IOLoop
+from tornado.netutil import ThreadedResolver
+from tornado.util import u
+
+# When this module is imported, it runs getaddrinfo on a thread. Since
+# the hostname is unicode, getaddrinfo attempts to import encodings.idna
+# but blocks on the import lock. Verify that ThreadedResolver avoids
+# this deadlock.
+
+resolver = ThreadedResolver()
+IOLoop.current().run_sync(lambda: resolver.resolve(u('tornadoweb.org'), 80))