On Wed, Sep 22, 2021 at 08:49:25PM -0400, John Snow wrote: > The single space is indeed required to successfully transmit the file > descriptor to QEMU.
Sending fds requires a payload of at least one byte, but I don't think that qemu cares which byte. Thus, while your choice of space is fine, the commit message may be a bit misleading at implying it must be space. > > Python 3.11 removes support for calling sendmsg directly from a > transport's socket. There is no other interface for doing this, our use > case is, I suspect, "quite unique". > > As far as I can tell, this is safe to do -- send_fd_scm is a synchronous > function and we can be guaranteed that the async coroutines will *not* be > running when it is invoked. In testing, it works correctly. > > I investigated quite thoroughly the possibility of creating my own > asyncio Transport (The class that ultimately manages the raw socket > object) so that I could manage the socket myself, but this is so wildly > invasive and unportable I scrapped the idea. It would involve a lot of > copy-pasting of various python utilities and classes just to re-create > the same infrastructure, and for extremely little benefit. Nah. > > Just boldly void the warranty instead, while I try to follow up on > https://bugs.python.org/issue43232 Bummer that we have to do that, but at least you are documenting the problems and pursuing a remedy upstream. > > Signed-off-by: John Snow <[email protected]> > --- > python/qemu/aqmp/qmp_client.py | 22 ++++++++++++++++++++++ > 1 file changed, 22 insertions(+) > > diff --git a/python/qemu/aqmp/qmp_client.py b/python/qemu/aqmp/qmp_client.py > index d2ad7459f9f..f987da02eb0 100644 > --- a/python/qemu/aqmp/qmp_client.py > +++ b/python/qemu/aqmp/qmp_client.py > @@ -9,6 +9,8 @@ > > import asyncio > import logging > +import socket > +import struct > from typing import ( > Dict, > List, > @@ -624,3 +626,23 @@ async def execute(self, cmd: str, > """ > msg = self.make_execute_msg(cmd, arguments, oob=oob) > return await self.execute_msg(msg) > + > + @upper_half > + @require(Runstate.RUNNING) > + def send_fd_scm(self, fd: int) -> None: > + """ > + Send a file descriptor to the remote via SCM_RIGHTS. > + """ > + assert self._writer is not None > + sock = self._writer.transport.get_extra_info('socket') > + > + if sock.family != socket.AF_UNIX: > + raise AQMPError("Sending file descriptors requires a UNIX > socket.") > + > + # Void the warranty sticker. > + # Access to sendmsg in asyncio is scheduled for removal in Python > 3.11. > + sock = sock._sock # pylint: disable=protected-access > + sock.sendmsg( > + [b' '], > + [(socket.SOL_SOCKET, socket.SCM_RIGHTS, struct.pack('@i', fd))] > + ) Reviewed-by: Eric Blake <[email protected]> -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
