summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2022-09-02 21:50:22 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2022-09-03 12:58:45 +0100
commit5964bb67bb20df7f411ee0650cf189504a05cf25 (patch)
tree9b8b1f4dddd6f937d56f413c3d69624fcca4d475
parent4b8de2e7d12667d69d86ffe6e9f85a7932c4c9a5 (diff)
downloadbitbake-5964bb67bb20df7f411ee0650cf189504a05cf25.tar.gz
asyncrpc/client: Fix unix domain socket chdir race issues
The connect_unix() call had a bug where if a relative path to a socket was passed (which the non-async client always does), and the current working directory was changed after the initial call, it would fail to reconnect if it became disconnected, since the socket couldn't be found relative to the new current working directory. To work around this, change the socket connection for UNIX domain sockets to be synchronous and change current working before connecting. This isn't ideal since the connection could block the entire event loop, but in practice this shouldn't happen since the socket are local files anyway. Help debugging and resolving from Joshua Watt. Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--lib/bb/asyncrpc/client.py22
1 files changed, 13 insertions, 9 deletions
diff --git a/lib/bb/asyncrpc/client.py b/lib/bb/asyncrpc/client.py
index 881434d2e..fa042bbe8 100644
--- a/lib/bb/asyncrpc/client.py
+++ b/lib/bb/asyncrpc/client.py
@@ -31,7 +31,17 @@ class AsyncClient(object):
async def connect_unix(self, path):
async def connect_sock():
- return await asyncio.open_unix_connection(path)
+ # AF_UNIX has path length issues so chdir here to workaround
+ cwd = os.getcwd()
+ try:
+ os.chdir(os.path.dirname(path))
+ # The socket must be opened synchronously so that CWD doesn't get
+ # changed out from underneath us so we pass as a sock into asyncio
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
+ sock.connect(os.path.basename(path))
+ finally:
+ os.chdir(cwd)
+ return await asyncio.open_unix_connection(sock=sock)
self._connect_sock = connect_sock
@@ -150,14 +160,8 @@ class Client(object):
setattr(self, m, self._get_downcall_wrapper(downcall))
def connect_unix(self, path):
- # AF_UNIX has path length issues so chdir here to workaround
- cwd = os.getcwd()
- try:
- os.chdir(os.path.dirname(path))
- self.loop.run_until_complete(self.client.connect_unix(os.path.basename(path)))
- self.loop.run_until_complete(self.client.connect())
- finally:
- os.chdir(cwd)
+ self.loop.run_until_complete(self.client.connect_unix(path))
+ self.loop.run_until_complete(self.client.connect())
@property
def max_chunk(self):