Skip to content

Commit 514d00d

Browse files
committed
python/qmp: add send_fd_scm directly to QEMUMonitorProtocol
It turns out you can do this directly from Python ... and because of this, you don't need to worry about setting the inheritability of the fds or spawning another process. Doing this is helpful because it allows QEMUMonitorProtocol to keep its file descriptor and socket object as private implementation details. /that/ is helpful in turn because it allows me to write a compatible, alternative implementation. Signed-off-by: John Snow <[email protected]> Reviewed-by: Hanna Reitz <[email protected]> Reviewed-by: Paolo Bonzini <[email protected]> Message-id: [email protected] Signed-off-by: John Snow <[email protected]>
1 parent d911acc commit 514d00d

File tree

2 files changed

+18
-47
lines changed

2 files changed

+18
-47
lines changed

python/qemu/machine/machine.py

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -213,48 +213,22 @@ def add_fd(self: _T, fd: int, fdset: int,
213213
def send_fd_scm(self, fd: Optional[int] = None,
214214
file_path: Optional[str] = None) -> int:
215215
"""
216-
Send an fd or file_path to socket_scm_helper.
216+
Send an fd or file_path to the remote via SCM_RIGHTS.
217217
218-
Exactly one of fd and file_path must be given.
219-
If it is file_path, the helper will open that file and pass its own fd.
218+
Exactly one of fd and file_path must be given. If it is
219+
file_path, the file will be opened read-only and the new file
220+
descriptor will be sent to the remote.
220221
"""
221-
# In iotest.py, the qmp should always use unix socket.
222-
assert self._qmp.is_scm_available()
223-
if self._socket_scm_helper is None:
224-
raise QEMUMachineError("No path to socket_scm_helper set")
225-
if not os.path.exists(self._socket_scm_helper):
226-
raise QEMUMachineError("%s does not exist" %
227-
self._socket_scm_helper)
228-
229-
# This did not exist before 3.4, but since then it is
230-
# mandatory for our purpose
231-
if hasattr(os, 'set_inheritable'):
232-
os.set_inheritable(self._qmp.get_sock_fd(), True)
233-
if fd is not None:
234-
os.set_inheritable(fd, True)
235-
236-
fd_param = ["%s" % self._socket_scm_helper,
237-
"%d" % self._qmp.get_sock_fd()]
238-
239222
if file_path is not None:
240223
assert fd is None
241-
fd_param.append(file_path)
224+
with open(file_path, "rb") as passfile:
225+
fd = passfile.fileno()
226+
self._qmp.send_fd_scm(fd)
242227
else:
243228
assert fd is not None
244-
fd_param.append(str(fd))
245-
246-
proc = subprocess.run(
247-
fd_param,
248-
stdin=subprocess.DEVNULL,
249-
stdout=subprocess.PIPE,
250-
stderr=subprocess.STDOUT,
251-
check=False,
252-
close_fds=False,
253-
)
254-
if proc.stdout:
255-
LOG.debug(proc.stdout)
229+
self._qmp.send_fd_scm(fd)
256230

257-
return proc.returncode
231+
return 0
258232

259233
@staticmethod
260234
def _remove_if_exists(path: str) -> None:

python/qemu/qmp/__init__.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import json
2222
import logging
2323
import socket
24+
import struct
2425
from types import TracebackType
2526
from typing import (
2627
Any,
@@ -408,18 +409,14 @@ def settimeout(self, timeout: Optional[float]) -> None:
408409
raise ValueError(msg)
409410
self.__sock.settimeout(timeout)
410411

411-
def get_sock_fd(self) -> int:
412+
def send_fd_scm(self, fd: int) -> None:
412413
"""
413-
Get the socket file descriptor.
414-
415-
@return The file descriptor number.
416-
"""
417-
return self.__sock.fileno()
418-
419-
def is_scm_available(self) -> bool:
414+
Send a file descriptor to the remote via SCM_RIGHTS.
420415
"""
421-
Check if the socket allows for SCM_RIGHTS.
416+
if self.__sock.family != socket.AF_UNIX:
417+
raise RuntimeError("Can't use SCM_RIGHTS on non-AF_UNIX socket.")
422418

423-
@return True if SCM_RIGHTS is available, otherwise False.
424-
"""
425-
return self.__sock.family == socket.AF_UNIX
419+
self.__sock.sendmsg(
420+
[b' '],
421+
[(socket.SOL_SOCKET, socket.SCM_RIGHTS, struct.pack('@i', fd))]
422+
)

0 commit comments

Comments
 (0)