After receiving descriptors with SCM_RIGHTS the socket channel resets O_NONBLOCK on each of them with fcntl(F_SETFL). macOS rejects F_SETFL on POSIX shared memory descriptors, so every message carrying such a descriptor caused the connection to drop. Those descriptors are passed in blocking mode anyway, so there is nothing to change on them. Query the flags with F_GETFL first and only issue F_SETFL when O_NONBLOCK is actually set.
Signed-off-by: Tim Pambor <[email protected]> --- io/channel-socket.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/io/channel-socket.c b/io/channel-socket.c index 7920cee639..1785fd5bfe 100644 --- a/io/channel-socket.c +++ b/io/channel-socket.c @@ -520,8 +520,23 @@ static bool qio_channel_handle_fds(int *fds, size_t nfds, } if (!preserve_blocking) { - /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */ - if (!qemu_set_blocking(*fd, true, errp)) { + /* + * O_NONBLOCK is preserved across SCM_RIGHTS so reset it. + * + * Some descriptors reject F_SETFL outright, e.g. POSIX + * shared memory on macOS. They are passed in blocking + * mode anyway, so only touch descriptors that have it set. + */ + int flags = fcntl(*fd, F_GETFL); + + if (flags < 0) { + error_setg_errno(errp, errno, + "Can't get file descriptor %d flags", *fd); + return false; + } + + if ((flags & O_NONBLOCK) && + !qemu_set_blocking(*fd, true, errp)) { return false; } } -- 2.55.0
