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 :|


Reply via email to