On Thu, Sep 11, 2025 at 12:20:04PM +0300, Vladimir Sementsov-Ogievskiy wrote: > We want to switch from qemu_socket_set_block() to newer > qemu_set_blocking(), which provides return status of operation, > to handle errors. > > Still, we want to keep qio_channel_socket_readv() interface clean, > as currently it set @fds and @nfds only on success. > > So, in case of error, we should to close all incoming fds and don't > touch user's @fds and @nfds. > > Let's make separate functions qio_channel_handle_fds() and > qio_channel_cleanup_fds(), to achieve what we want. > > Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@yandex-team.ru> > --- > io/channel-socket.c | 73 +++++++++++++++++++++++++++++++++++---------- > 1 file changed, 57 insertions(+), 16 deletions(-) > > diff --git a/io/channel-socket.c b/io/channel-socket.c > index f7e3cb9742..afae97b2ef 100644 > --- a/io/channel-socket.c > +++ b/io/channel-socket.c > @@ -464,8 +464,7 @@ static void qio_channel_socket_finalize(Object *obj) > > #ifndef WIN32 > static void qio_channel_socket_copy_fds(struct msghdr *msg, > - int **fds, size_t *nfds, > - bool preserve_blocking) > + int **fds, size_t *nfds) > { > struct cmsghdr *cmsg; > > @@ -473,7 +472,7 @@ static void qio_channel_socket_copy_fds(struct msghdr > *msg, > *fds = NULL; > > for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { > - int fd_size, i; > + int fd_size; > int gotfds; > > if (cmsg->cmsg_len < CMSG_LEN(sizeof(int)) || > @@ -491,24 +490,54 @@ static void qio_channel_socket_copy_fds(struct msghdr > *msg, > gotfds = fd_size / sizeof(int); > *fds = g_renew(int, *fds, *nfds + gotfds); > memcpy(*fds + *nfds, CMSG_DATA(cmsg), fd_size); > + *nfds += gotfds; > + } > +} > > - for (i = 0; i < gotfds; i++) { > - int fd = (*fds)[*nfds + i]; > - if (fd < 0) { > - continue; > - } > +static bool qio_channel_handle_fds(int *fds, size_t nfds, > + bool preserve_blocking, Error **errp) > +{ > + int *end = fds + nfds, *fd; > + > +#ifdef MSG_CMSG_CLOEXEC > + if (preserve_blocking) { > + /* Nothing to do */ > + return true; > + } > +#endif > > - if (!preserve_blocking) { > - /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */ > - qemu_socket_set_block(fd); > + for (fd = fds; fd != end; fd++) { > + if (*fd < 0) { > + continue; > + } > + > + if (!preserve_blocking) { > + /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */ > + if (!qemu_set_blocking(*fd, true, errp)) { > + return false; > } > + } > > #ifndef MSG_CMSG_CLOEXEC > - qemu_set_cloexec(fd); > + qemu_set_cloexec(*fd); > #endif > + } > + > + return true; > +} > + > +static void qio_channel_cleanup_fds(int *fds, size_t nfds)
Suggest we change this to ... qio_channel_cleanup_fds(int **fds, size_t *nfds) > +{ > + int *end = fds + nfds, *fd; > + > + for (fd = fds; fd != end; fd++) { I can't help feeling this would be clearer as for (size_t i = 0; i < nfds; i++) { > + if (*fd < 0) { > + continue; > } > - *nfds += gotfds; > + close(*fd); > } > + > + g_free(fds); Then here we can use: g_clear_poointer(fds, g_free); *nfds = 0; > } > > > @@ -559,9 +588,21 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc, > } > > if (fds && nfds) { > - qio_channel_socket_copy_fds( > - &msg, fds, nfds, > - flags & QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING); > + int *local_fds; > + size_t local_nfds; > + bool preserve_blocking = > + flags & QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING; > + > + qio_channel_socket_copy_fds(&msg, &local_fds, &local_nfds); > + > + if (!qio_channel_handle_fds(local_fds, local_nfds, > + preserve_blocking, errp)) { > + qio_channel_cleanup_fds(local_fds, local_nfds); > + return -1; > + } > + > + *fds = local_fds; > + *nfds = local_nfds; We could eliminate the 'local_fds' / 'local_nfds' here and directly use 'fds' and 'nfds' when we make qio_channel_cleanup_fds responsible for clearing the pointers it receives. > } > > return ret; > -- > 2.48.1 > With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|