Skip to content

Commit

Permalink
USB/IP: Run Blocking Operations in Thread
Browse files Browse the repository at this point in the history
Some sysfs file writes block for more than 100 ms, which causes an
asyncio warning. Run those blocking writes in threads, so the event loop
isn't blocked.
  • Loading branch information
holesch committed Aug 22, 2024
1 parent b9a127a commit 56f700c
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 6 deletions.
14 changes: 10 additions & 4 deletions not_my_board/_usbip.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,15 @@ def refresh(self):
async def _context_stack(self, stack):
await stack.enter_async_context(self._lock)
await self.available()
stack.callback(self.stop_export)
stack.push_async_callback(self.stop_export)

def stop_export(self):
async def stop_export(self):
if self._is_exported:
try:
(self._sysfs_path / "usbip_sockfd").write_text("-1\n")
# This can block for ~ 250 ms. Run it in a thread.
await util.run_in_thread(
(self._sysfs_path / "usbip_sockfd").write_text, "-1\n"
)
except (OSError, FileNotFoundError):
# client might have disconnected or device disappeared
pass
Expand Down Expand Up @@ -192,7 +195,10 @@ async def _ensure_usbip_host_driver(self):
logger.info(
'Unbinding USB device %s from driver "%s"', self._busid, driver_name
)
(driver_path / "unbind").write_text(self._busid)
# Unbinding can take more than 100 ms. Run in Thread.
await util.run_in_thread(
(driver_path / "unbind").write_text, self._busid
)
await self._bind_usbip_host_driver()
elif self._sysfs_path.exists():
await self._bind_usbip_host_driver()
Expand Down
1 change: 1 addition & 0 deletions not_my_board/_util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
relay_streams,
run,
run_concurrently,
run_in_thread,
)
from ._logging import configure_logging
from ._matching import find_matching
Expand Down
8 changes: 6 additions & 2 deletions not_my_board/_util/_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,13 @@ async def __aexit__(self, exc_type, exc, tb):
async def flock(f):
"""File lock as a context manager"""

loop = asyncio.get_running_loop()
try:
await loop.run_in_executor(None, fcntl.flock, f.fileno(), fcntl.LOCK_EX)
await run_in_thread(fcntl.flock, f.fileno(), fcntl.LOCK_EX)
yield
finally:
fcntl.flock(f, fcntl.LOCK_UN)


async def run_in_thread(func, *args):
loop = asyncio.get_running_loop()
return await loop.run_in_executor(None, func, *args)

0 comments on commit 56f700c

Please sign in to comment.