On Thu, Oct 22, 2026 at 03:47:24PM +0200, Tim Pambor wrote:
> 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)) {
I'd be inclined to put this logic in qemu_set_blocking itself
so that it does the right thing for all possible callers.
At that point we might as well get rid of the use of
g_unix_set_fd_nonblocking in that function and directly call
fcntl so we avoid the duplicate F_GETFL calls, eg something more
like:
int flags, newflags;
flag = fcntl(fd, F_GETFL);
if (flags < 0) {
error_setg_errno(....)
return -1;
}
if (nonblock)
newflags = flags | O_NONBLOCK;
else
newflags = flags & ~O_NONBLOCK;
if (newflags != flags &&
fcntl(fd, F_SETFL, newflags) < 0) {
error_setg_errno(...);
return -1;
}
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|