Skip to content

Commit

Permalink
remote: spawn a separate thread to avoid deadlocks
Browse files Browse the repository at this point in the history
  • Loading branch information
tesuji committed Feb 11, 2025
1 parent 9b39bb1 commit bebe58f
Showing 1 changed file with 12 additions and 11 deletions.
23 changes: 12 additions & 11 deletions pwnlib/tubes/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from __future__ import division

import asyncio
import concurrent
import socket
import socks

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

def run_async_in_thread(coro):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
future = loop.run_until_complete(coro)
loop.close()
return future

# Using asyncio to avoid blocking when DNS resolution fail. It's probably better
# to use async all the ways to `sock.connect`. However, let's keep the changes
# small until we have the needs.
def sync_getaddrinfo(*args):
coro = async_getaddrinfo(*args)
try:
loop = asyncio.get_event_loop()
if loop.is_running():
# If an event loop is already running, use it to run the async function
future = asyncio.run_coroutine_threadsafe(coro, loop)
return future.result()
except RuntimeError:
pass
# If no event loop is running, create a new one
return asyncio.run(coro)
# Run in a a seperate thread to avoid deadlocks when users nest eventloops.
with concurrent.futures.ThreadPoolExecutor() as executor:
future = executor.submit(run_async_in_thread, async_getaddrinfo(*args))
return future.result()

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

0 comments on commit bebe58f

Please sign in to comment.