Skip to content

Commit bebe58f

Browse files
committed
remote: spawn a separate thread to avoid deadlocks
1 parent 9b39bb1 commit bebe58f

File tree

1 file changed

+12
-11
lines changed

1 file changed

+12
-11
lines changed

pwnlib/tubes/remote.py

+12-11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from __future__ import division
33

44
import asyncio
5+
import concurrent
56
import socket
67
import socks
78

@@ -118,21 +119,21 @@ async def async_getaddrinfo(host, port, fam=0, typ=0, proto=0, flags=0):
118119
result = []
119120
return result
120121

122+
def run_async_in_thread(coro):
123+
loop = asyncio.new_event_loop()
124+
asyncio.set_event_loop(loop)
125+
future = loop.run_until_complete(coro)
126+
loop.close()
127+
return future
128+
121129
# Using asyncio to avoid blocking when DNS resolution fail. It's probably better
122130
# to use async all the ways to `sock.connect`. However, let's keep the changes
123131
# small until we have the needs.
124132
def sync_getaddrinfo(*args):
125-
coro = async_getaddrinfo(*args)
126-
try:
127-
loop = asyncio.get_event_loop()
128-
if loop.is_running():
129-
# If an event loop is already running, use it to run the async function
130-
future = asyncio.run_coroutine_threadsafe(coro, loop)
131-
return future.result()
132-
except RuntimeError:
133-
pass
134-
# If no event loop is running, create a new one
135-
return asyncio.run(coro)
133+
# Run in a a seperate thread to avoid deadlocks when users nest eventloops.
134+
with concurrent.futures.ThreadPoolExecutor() as executor:
135+
future = executor.submit(run_async_in_thread, async_getaddrinfo(*args))
136+
return future.result()
136137

137138
with self.waitfor('Opening connection to %s on port %s' % (self.rhost, self.rport)) as h:
138139
hostnames = sync_getaddrinfo(self.rhost, self.rport, fam, typ, 0, socket.AI_PASSIVE)

0 commit comments

Comments
 (0)