{"id":10045,"date":"2016-01-08T16:11:10","date_gmt":"2016-01-08T14:11:10","guid":{"rendered":"http:\/\/www.webcodegeeks.com\/?p=10045"},"modified":"2016-01-02T13:11:39","modified_gmt":"2016-01-02T11:11:39","slug":"deadlock-python-getaddrinfo","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/","title":{"rendered":"How To Deadlock Your Python With getaddrinfo"},"content":{"rendered":"<p>What happens if you run this code?<\/p>\n<pre class=\"brush:python\">import os\r\nimport socket\r\nimport threading\r\n\r\n\r\ndef lookup():\r\n    socket.getaddrinfo('python.org', 80)\r\n\r\nt = threading.Thread(target=lookup)\r\nt.start()\r\nif os.fork():\r\n    # Parent waits for child.\r\n    os.wait()\r\nelse:\r\n    # Child hangs here.\r\n    socket.getaddrinfo('mongodb.org', 80)<\/pre>\n<p>On Linux, it completes in milliseconds. On Mac, it usually hangs. Why?<\/p>\n<h2>Journey To The Center Of The Interpreter<\/h2>\n<p>Anna Herlihy and I tackled this question a few months ago. It didn&#8217;t look like the code example above\u2014not at first. We&#8217;d come across an article by Anthony Fejes reporting that the new PyMongo 3.0 didn&#8217;t work with his software, which combined multithreading with multiprocessing. Often, he&#8217;d create a MongoClient, then fork, and in the child process the MongoClient couldn&#8217;t connect to any servers:<\/p>\n<pre class=\" brush:python\">import os\r\n\r\nfrom pymongo import MongoClient\r\n\r\n\r\nclient = MongoClient()\r\nif os.fork():\r\n    # Parent waits for child.\r\n    os.wait()\r\nelse:\r\n    # After 30 sec, \"ServerSelectionTimeoutError: No servers found\".\r\n    client.admin.command('ping')<\/pre>\n<p>In PyMongo 3, a MongoClient begins connecting to your server with a background thread. This lets it parallelize the connections if there are several servers, and it prevents your code from blocking, even if some of the connections are slow. This worked fine, except in Anthony Fejes&#8217;s scenario: when the MongoClient constructor was immediately followed by a <code>fork<\/code>, the MongoClient was broken in the child process.<\/p>\n<p>Anna investigated. She could reproduce the timeout on her Mac, but not on a Linux box.<\/p>\n<p>She descended through PyMongo&#8217;s layers using the PyCharm debugger and print statements, and found that the child process hung when it tried to open its first connection to MongoDB. It reached this line and stopped cold:<\/p>\n<pre class=\" brush:python\">infos = socket.getaddrinfo(host, port)<\/pre>\n<p>It reminded me of the <code>getaddrinfo<\/code> quirk I&#8217;d learned about during a side-trip while I was <a href=\"https:\/\/emptysqua.re\/blog\/weird-green-bug\/\">debugging a completely unrelated <code>getaddrinfo<\/code> deadlock last year<\/a>. The quirk is this: on some platforms, Python locks around <code>getaddrinfo<\/code> calls, allowing only one thread to resolve a name at a time. In Python&#8217;s standard socketmodule.c:<\/p>\n<pre class=\" brush:python\">\/* On systems on which getaddrinfo() is believed to not be thread-safe,\r\n   (this includes the getaddrinfo emulation) protect access with a lock. *\/\r\n#if defined(WITH_THREAD) &amp;&amp; (defined(__APPLE__) || \\\r\n    (defined(__FreeBSD__) &amp;&amp; __FreeBSD_version+0 &lt; 503000) || \\\r\n    defined(__OpenBSD__) || defined(__NetBSD__) || \\\r\n    defined(__VMS) || !defined(HAVE_GETADDRINFO))\r\n#define USE_GETADDRINFO_LOCK\r\n#endif<\/pre>\n<p>So Anna added some printfs in socketmodule.c, rebuilt her copy of CPython on Mac, and descended yet deeper into the layers. Sure enough, the interpreter deadlocks here in the child process:<\/p>\n<pre class=\" brush:python\">static PyObject *\r\nsocket_getaddrinfo(PyObject *self, PyObject *args)\r\n{\r\n    \/* ... *\/\r\n    Py_BEGIN_ALLOW_THREADS\r\n    printf(\"getting gai lock...\\n\");\r\n    ACQUIRE_GETADDRINFO_LOCK\r\n    printf(\"got gai lock\\n\");\r\n    error = getaddrinfo(hptr, pptr, &amp;hints, &amp;res0);\r\n    Py_END_ALLOW_THREADS\r\n    RELEASE_GETADDRINFO_LOCK<\/pre>\n<p>The macro <code>Py_BEGIN_ALLOW_THREADS<\/code> drops the Global Interpreter Lock, so other Python threads can run while this one waits for <code>getaddrinfo<\/code>. Then, depending on the platform, <code>ACQUIRE_GETADDRINFO_LOCK<\/code> does nothing (Linux) or grabs a lock (Mac). Once <code>getaddrinfo<\/code> returns, this code first reacquires the Global Interpreter Lock, then drops the <code>getaddrinfo<\/code> lock (if there is one).<\/p>\n<p>So, on Linux, these lines allow concurrent hostname lookups. On Mac, only one thread can wait for <code>getaddrinfo<\/code> at a time. But why does forking cause a total deadlock?<\/p>\n<h2>Diagnosis<\/h2>\n<p>Consider our original example:<\/p>\n<pre class=\" brush:python\">def lookup():\r\n    socket.getaddrinfo('python.org', 80)\r\n\r\nt = threading.Thread(target=lookup)\r\nt.start()\r\nif os.fork():\r\n    # Parent waits for child.\r\n    os.wait()\r\nelse:\r\n    # Child hangs here.\r\n    socket.getaddrinfo('mongodb.org', 80)<\/pre>\n<p>The <code>lookup<\/code> thread starts, drops the Global Interpreter Lock, grabs the <code>getaddrinfo<\/code> lock, and waits for <code>getaddrinfo<\/code>. Since the GIL is available, the main thread takes it and resumes. The main thread&#8217;s next call is <code>fork<\/code>.<\/p>\n<p>When a process forks, only the thread that called <code>fork<\/code> is copied into the child process. Thus in the child process, the main thread continues and the <code>lookup<\/code> thread is gone. But that was the thread holding the <code>getaddrinfo<\/code> lock! In the child process, the <code>getaddrinfo<\/code> lock will never be released\u2014the thread whose job it was to release it is kaput.<\/p>\n<p>In this stripped-down example, the next event is the child process calling <code>getaddrinfo<\/code> on the main thread. The <code>getaddrinfo<\/code> lock is never released, so the process simply deadlocks. In the actual PyMongo scenario, the main thread isn&#8217;t blocked, but whenever it tries to use a MongoDB server it times out. Anna explained, &#8220;in the child process, the <code>getaddrinfo<\/code> lock will never be unlocked\u2014the thread that locked it was not copied to the child\u2014so the background thread can never resolve the server&#8217;s hostname and connect. The child&#8217;s main thread will then time out.&#8221;<\/p>\n<p>(A digression: If this were a C program it would switch threads unpredictably, and it would not always deadlock. Sometimes the <code>lookup<\/code> thread would finish <code>getaddrinfo<\/code> before the main thread forked, sometimes not. But in Python, thread switching is infrequent and predictable. Threads are allowed to switch every 1000 bytecodes in Python 2, or every 15 ms in Python 3. If multiple threads are waiting for the GIL, they will tend to switch every time they drop the GIL with <code>Py_BEGIN_ALLOW_THREADS<\/code> and wait for a C call like <code>getaddrinfo<\/code>. So in Python, the deadlock is practically deterministic.)<\/p>\n<h2>Verification<\/h2>\n<p>Anna and I had our hypothesis. But could we prove it?<\/p>\n<p>One test was, if we waited until the background thread had probably dropped the <code>getaddrinfo<\/code> lock before we forked, we shouldn&#8217;t see a deadlock. Indeed, we avoided the deadlock if we added a tiny sleep before the fork:<\/p>\n<pre class=\" brush:python\">client = MongoClient()\r\ntime.sleep(0.1)\r\nif os.fork():\r\n    # ... and so on ...<\/pre>\n<p>We read the <code>ifdef<\/code> in sockmodule.c again and devised another way to verify our hypothesis: we should deadlock on Mac and OpenBSD, but not Linux or FreeBSD. We created a few kinds of virtual machines and voil\u00e0, they deadlocked or didn&#8217;t, as expected.<\/p>\n<p>(Windows would deadlock too, except Python on Windows can&#8217;t fork.)<\/p>\n<h2>Why Now?<\/h2>\n<p>Why was this bug reported in PyMongo 3, and not our previous driver version PyMongo 2?<\/p>\n<p>PyMongo 2 had a simpler, less concurrent design: if you create a single MongoClient it spawns no background threads, so you can <code>fork<\/code> safely.<\/p>\n<p>The old PyMongo 2 MongoReplicaSetClient did use a background thread, but its constructor blocked until the background thread completed its connections. This code was slow but fairly safe:<\/p>\n<pre class=\" brush:python\"># Blocks until initial connections are done.\r\nclient = MongoReplicaSetClient(hosts, replicaSet=\"rs\")\r\n\r\nif os.fork():\r\n    os.wait()\r\nelse:\r\n    client.admin.command('ping')<\/pre>\n<p>In PyMongo 3, however, MongoReplicaSetClient is gone. MongoClient now handles connections to single servers or replica sets. The new client&#8217;s constructor spawns one or more threads to begin connecting, and it returns immediately instead of blocking. Thus, a background thread is <em>usually<\/em> holding the <code>getaddrinfo<\/code> lock while the main thread executes its next few statements.<\/p>\n<h2>Just Don&#8217;t Do That, Then<\/h2>\n<p>Unfortunately, there is no real solution to this bug. We won&#8217;t go back to the old single-threaded, blocking MongoClient\u2014the new code&#8217;s advantages are too great. Besides, even the slow old code didn&#8217;t make it completely safe to fork. You were less <em>likely<\/em> to fork while a thread was holding the <code>getaddrinfo<\/code> lock, but if you used MongoReplicaSetClient the risk of deadlock was always there.<\/p>\n<p>Anna and I decided that the use-case for forking right after constructing a MongoClient isn&#8217;t common or necessary, anyway. You&#8217;re better off forking first:<\/p>\n<pre class=\" brush:python\">if os.fork():\r\n    os.wait()\r\nelse:\r\n    # Safe to create the client in the child process.\r\n    client = MongoClient()\r\n    client.admin.command('ping')<\/pre>\n<p>Forking first is a good idea with PyMongo or any other network library\u2014it&#8217;s terribly hard to make libraries fork-proof, best not to risk it.<\/p>\n<p>If you must create the client first, you can tell it not to start its background threads until needed, like this:<\/p>\n<pre class=\"brush:python\">client = MongoClient(connect=False)\r\nif os.fork():\r\n    os.wait()\r\nelse:\r\n    # Threads start on demand and connect to server.\r\n    client.admin.command('ping')<\/pre>\n<h2>Warning, Deadlock Ahead!<\/h2>\n<p>We had convenient workarounds. But how do we prevent the next user like Anthony from spending days debugging this?<\/p>\n<p>Anna found a way to detect if MongoClient was being used riskily and print a warning from the child process:<\/p>\n<pre class=\"brush:python\">UserWarning: MongoClient opened before fork. Create MongoClient\r\n    with connect=False, or create client after forking. See PyMongo's\r\n    documentation for details:\r\n\r\n    http:\/\/bit.ly\/pymongo-faq#using-pymongo-with-multiprocessing<\/pre>\n<p>We shipped this fix with PyMongo 3.1 in November.<\/p>\n<p>Next time: the <code>getaddrinfo<\/code> lock strikes again, and I spend a week patching asyncio in the Python standard library.<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"http:\/\/emptysqua.re\/blog\/getaddrinfo-deadlock\/\">How To Deadlock Your Python With getaddrinfo<\/a> from our <a href=\"http:\/\/www.webcodegeeks.com\/join-us\/wcg\/\">WCG partner<\/a> Jesse Davis at the <a href=\"http:\/\/emptysqua.re\/blog\/\">A. Jesse Jiryu Davis<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>What happens if you run this code? import os import socket import threading def lookup(): socket.getaddrinfo(&#8216;python.org&#8217;, 80) t = threading.Thread(target=lookup) t.start() if os.fork(): # Parent waits for child. os.wait() else: # Child hangs here. socket.getaddrinfo(&#8216;mongodb.org&#8217;, 80) On Linux, it completes in milliseconds. On Mac, it usually hangs. Why? Journey To The Center Of The Interpreter &hellip;<\/p>\n","protected":false},"author":29,"featured_media":1651,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[53],"tags":[],"class_list":["post-10045","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-python"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>How To Deadlock Your Python With getaddrinfo - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"What happens if you run this code? import os import socket import threading def lookup(): socket.getaddrinfo(&#039;python.org&#039;, 80) t =\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How To Deadlock Your Python With getaddrinfo - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"What happens if you run this code? import os import socket import threading def lookup(): socket.getaddrinfo(&#039;python.org&#039;, 80) t =\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2016-01-08T14:11:10+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Jesse Davis\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/jessejiryudavis\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jesse Davis\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/\"},\"author\":{\"name\":\"Jesse Davis\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/294d6819cb410ef55f273ecf25426c56\"},\"headline\":\"How To Deadlock Your Python With getaddrinfo\",\"datePublished\":\"2016-01-08T14:11:10+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/\"},\"wordCount\":1118,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\",\"articleSection\":[\"Python\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/\",\"name\":\"How To Deadlock Your Python With getaddrinfo - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\",\"datePublished\":\"2016-01-08T14:11:10+00:00\",\"description\":\"What happens if you run this code? import os import socket import threading def lookup(): socket.getaddrinfo('python.org', 80) t =\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Python\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/python\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"How To Deadlock Your Python With getaddrinfo\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/294d6819cb410ef55f273ecf25426c56\",\"name\":\"Jesse Davis\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/2db0fdaadd8cd6b86d93e1205e30dd3b43e3c46b91826513ab618934c3db8cf9?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/2db0fdaadd8cd6b86d93e1205e30dd3b43e3c46b91826513ab618934c3db8cf9?s=96&d=mm&r=g\",\"caption\":\"Jesse Davis\"},\"description\":\"Jesse is a senior engineer at MongoDB in New York City. He specializes in Python, MongoDB drivers, and asynchronous frameworks.\",\"sameAs\":[\"http:\/\/emptysqua.re\/blog\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/jessejiryudavis\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/jesse-davis\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How To Deadlock Your Python With getaddrinfo - Web Code Geeks - 2026","description":"What happens if you run this code? import os import socket import threading def lookup(): socket.getaddrinfo('python.org', 80) t =","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/","og_locale":"en_US","og_type":"article","og_title":"How To Deadlock Your Python With getaddrinfo - Web Code Geeks - 2026","og_description":"What happens if you run this code? import os import socket import threading def lookup(): socket.getaddrinfo('python.org', 80) t =","og_url":"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2016-01-08T14:11:10+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","type":"image\/jpeg"}],"author":"Jesse Davis","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/jessejiryudavis","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Jesse Davis","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/"},"author":{"name":"Jesse Davis","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/294d6819cb410ef55f273ecf25426c56"},"headline":"How To Deadlock Your Python With getaddrinfo","datePublished":"2016-01-08T14:11:10+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/"},"wordCount":1118,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","articleSection":["Python"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/","url":"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/","name":"How To Deadlock Your Python With getaddrinfo - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#primaryimage"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","datePublished":"2016-01-08T14:11:10+00:00","description":"What happens if you run this code? import os import socket import threading def lookup(): socket.getaddrinfo('python.org', 80) t =","breadcrumb":{"@id":"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.webcodegeeks.com\/python\/deadlock-python-getaddrinfo\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Python","item":"https:\/\/www.webcodegeeks.com\/category\/python\/"},{"@type":"ListItem","position":3,"name":"How To Deadlock Your Python With getaddrinfo"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/294d6819cb410ef55f273ecf25426c56","name":"Jesse Davis","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/2db0fdaadd8cd6b86d93e1205e30dd3b43e3c46b91826513ab618934c3db8cf9?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/2db0fdaadd8cd6b86d93e1205e30dd3b43e3c46b91826513ab618934c3db8cf9?s=96&d=mm&r=g","caption":"Jesse Davis"},"description":"Jesse is a senior engineer at MongoDB in New York City. He specializes in Python, MongoDB drivers, and asynchronous frameworks.","sameAs":["http:\/\/emptysqua.re\/blog\/","https:\/\/x.com\/https:\/\/twitter.com\/jessejiryudavis"],"url":"https:\/\/www.webcodegeeks.com\/author\/jesse-davis\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/10045","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/29"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=10045"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/10045\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/1651"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=10045"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=10045"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=10045"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}