On Tue, Sep 16, 2025 at 04:13:53PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> Currently, we just always pass NULL as errp argument. That doesn't
> look good.
> 
> Some realizations of interface may actually report errors.
> Channel-socket realization actually either ignore or crash on
> errors, but we are going to straighten it out to always reporting
> an errp in further commits.
> 
> So, convert all callers to either handle the error (where environment
> allows) or explicitly use &error_abort.
> 
> Take also a chance to change the return value to more convenient
> bool (keeping also in mind, that underlying realizations may
> return -1 on failure, not -errno).
> 
> Suggested-by: Daniel P. Berrangé <[email protected]>
> Signed-off-by: Vladimir Sementsov-Ogievskiy <[email protected]>
> Reviewed-by: Daniel P. Berrangé <[email protected]>
> ---
>  block/nbd.c                      |  4 +++-
>  chardev/char-socket.c            | 20 ++++++++++++++++----
>  hw/remote/proxy.c                |  6 +++++-
>  hw/remote/remote-obj.c           |  6 +++++-
>  hw/vfio-user/proxy.c             | 11 ++++++++---
>  include/io/channel.h             |  6 +++---
>  io/channel.c                     |  4 ++--

This needed to change channel-tls.c and channel-websock.c because
their impls of qio_channel_set_blocking callback in turn called
qio_channel_set_blocking, so had an int vs bool conversion mistake
introduced in this patch.

>  nbd/server.c                     |  4 +++-
>  scsi/qemu-pr-helper.c            |  9 ++++++---
>  tests/unit/io-channel-helpers.c  |  5 +++--
>  tests/unit/test-io-channel-tls.c |  4 ++--
>  tools/i386/qemu-vmsr-helper.c    |  6 ++++--
>  ui/vnc.c                         |  2 +-
>  util/vhost-user-server.c         |  7 ++++++-
>  14 files changed, 67 insertions(+), 27 deletions(-)
> 
> diff --git a/block/nbd.c b/block/nbd.c
> index d5a2b21c6d..5d231d5c4e 100644
> --- a/block/nbd.c
> +++ b/block/nbd.c
> @@ -351,7 +351,9 @@ int coroutine_fn 
> nbd_co_do_establish_connection(BlockDriverState *bs,
>          return ret;
>      }
>  
> -    qio_channel_set_blocking(s->ioc, false, NULL);
> +    if (!qio_channel_set_blocking(s->ioc, false, errp)) {
> +        return -EINVAL;
> +    }
>      qio_channel_set_follow_coroutine_ctx(s->ioc, true);
>  
>      /* successfully connected */
> diff --git a/chardev/char-socket.c b/chardev/char-socket.c
> index 1be078dfc0..cb4ec78ebe 100644
> --- a/chardev/char-socket.c
> +++ b/chardev/char-socket.c
> @@ -530,16 +530,24 @@ static int tcp_chr_sync_read(Chardev *chr, const 
> uint8_t *buf, int len)
>      SocketChardev *s = SOCKET_CHARDEV(chr);
>      int size;
>      int saved_errno;
> +    Error *local_err = NULL;
>  
>      if (s->state != TCP_CHARDEV_STATE_CONNECTED) {
>          return 0;
>      }
>  
> -    qio_channel_set_blocking(s->ioc, true, NULL);
> +    if (!qio_channel_set_blocking(s->ioc, true, &local_err)) {
> +        error_report_err(local_err);
> +        return -1;
> +    }
>      size = tcp_chr_recv(chr, (void *) buf, len);
>      saved_errno = errno;
>      if (s->state != TCP_CHARDEV_STATE_DISCONNECTED) {
> -        qio_channel_set_blocking(s->ioc, false, NULL);
> +        if (!qio_channel_set_blocking(s->ioc, false, &local_err)) {
> +            error_report_err(local_err);
> +            /* failed to recover non-blocking state */
> +            tcp_chr_disconnect(chr);
> +        }
>      }
>      if (size == 0) {
>          /* connection closed */
> @@ -884,18 +892,22 @@ static void tcp_chr_set_client_ioc_name(Chardev *chr,
>  static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
>  {
>      SocketChardev *s = SOCKET_CHARDEV(chr);
> +    Error *local_err = NULL;
>  
>      if (s->state != TCP_CHARDEV_STATE_CONNECTING) {
>          return -1;
>      }
>  
> +    if (!qio_channel_set_blocking(QIO_CHANNEL(sioc), false, &local_err)) {
> +        error_report_err(local_err);
> +        return -1;
> +    }
> +
>      s->ioc = QIO_CHANNEL(sioc);
>      object_ref(OBJECT(sioc));
>      s->sioc = sioc;
>      object_ref(OBJECT(sioc));
>  
> -    qio_channel_set_blocking(s->ioc, false, NULL);
> -
>      if (s->do_nodelay) {
>          qio_channel_set_delay(s->ioc, false);
>      }
> diff --git a/hw/remote/proxy.c b/hw/remote/proxy.c
> index b0165aa2a1..18e0f7a064 100644
> --- a/hw/remote/proxy.c
> +++ b/hw/remote/proxy.c
> @@ -112,8 +112,12 @@ static void pci_proxy_dev_realize(PCIDevice *device, 
> Error **errp)
>          return;
>      }
>  
> +    if (!qio_channel_set_blocking(dev->ioc, true, errp)) {
> +        object_unref(dev->ioc);
> +        return;
> +    }
> +
>      qemu_mutex_init(&dev->io_mutex);
> -    qio_channel_set_blocking(dev->ioc, true, NULL);
>  
>      pci_conf[PCI_LATENCY_TIMER] = 0xff;
>      pci_conf[PCI_INTERRUPT_PIN] = 0x01;
> diff --git a/hw/remote/remote-obj.c b/hw/remote/remote-obj.c
> index 85882902d7..3402068ab9 100644
> --- a/hw/remote/remote-obj.c
> +++ b/hw/remote/remote-obj.c
> @@ -107,7 +107,11 @@ static void remote_object_machine_done(Notifier 
> *notifier, void *data)
>          error_report_err(err);
>          return;
>      }
> -    qio_channel_set_blocking(ioc, false, NULL);
> +    if (!qio_channel_set_blocking(ioc, false, &err)) {
> +        error_report_err(err);
> +        object_unref(OBJECT(ioc));
> +        return;
> +    }
>  
>      o->dev = dev;
>  
> diff --git a/hw/vfio-user/proxy.c b/hw/vfio-user/proxy.c
> index 2c03d49f97..bbd7ec243d 100644
> --- a/hw/vfio-user/proxy.c
> +++ b/hw/vfio-user/proxy.c
> @@ -886,10 +886,11 @@ VFIOUserProxy *vfio_user_connect_dev(SocketAddress 
> *addr, Error **errp)
>      sioc = qio_channel_socket_new();
>      ioc = QIO_CHANNEL(sioc);
>      if (qio_channel_socket_connect_sync(sioc, addr, errp) < 0) {
> -        object_unref(OBJECT(ioc));
> -        return NULL;
> +        goto fail;
> +    }
> +    if (!qio_channel_set_blocking(ioc, false, errp)) {
> +        goto fail;
>      }
> -    qio_channel_set_blocking(ioc, false, NULL);
>  
>      proxy = g_malloc0(sizeof(VFIOUserProxy));
>      proxy->sockname = g_strdup_printf("unix:%s", sockname);
> @@ -923,6 +924,10 @@ VFIOUserProxy *vfio_user_connect_dev(SocketAddress 
> *addr, Error **errp)
>      QLIST_INSERT_HEAD(&vfio_user_sockets, proxy, next);
>  
>      return proxy;
> +
> +fail:
> +    object_unref(OBJECT(ioc));
> +    return NULL;
>  }
>  
>  void vfio_user_set_handler(VFIODevice *vbasedev,
> diff --git a/include/io/channel.h b/include/io/channel.h
> index c7f64506f7..999a8f5f23 100644
> --- a/include/io/channel.h
> +++ b/include/io/channel.h
> @@ -531,9 +531,9 @@ int coroutine_mixed_fn qio_channel_write_all(QIOChannel 
> *ioc,
>   * return QIO_CHANNEL_ERR_BLOCK if they would otherwise
>   * block on I/O
>   */
> -int qio_channel_set_blocking(QIOChannel *ioc,
> -                             bool enabled,
> -                             Error **errp);
> +bool qio_channel_set_blocking(QIOChannel *ioc,
> +                              bool enabled,
> +                              Error **errp);
>  
>  /**
>   * qio_channel_set_follow_coroutine_ctx:
> diff --git a/io/channel.c b/io/channel.c
> index ebd9322765..852e684938 100644
> --- a/io/channel.c
> +++ b/io/channel.c
> @@ -359,12 +359,12 @@ int coroutine_mixed_fn qio_channel_write_all(QIOChannel 
> *ioc,
>  }
>  
>  
> -int qio_channel_set_blocking(QIOChannel *ioc,
> +bool qio_channel_set_blocking(QIOChannel *ioc,
>                                bool enabled,
>                                Error **errp)
>  {
>      QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
> -    return klass->io_set_blocking(ioc, enabled, errp);
> +    return klass->io_set_blocking(ioc, enabled, errp) == 0;
>  }
>  
>  
> diff --git a/nbd/server.c b/nbd/server.c
> index d242be9811..acec0487a8 100644
> --- a/nbd/server.c
> +++ b/nbd/server.c
> @@ -1411,7 +1411,9 @@ static coroutine_fn int nbd_negotiate(NBDClient 
> *client, Error **errp)
>          ....options sent, ending in NBD_OPT_EXPORT_NAME or NBD_OPT_GO....
>       */
>  
> -    qio_channel_set_blocking(client->ioc, false, NULL);
> +    if (!qio_channel_set_blocking(client->ioc, false, errp)) {
> +        return -EINVAL;
> +    }
>      qio_channel_set_follow_coroutine_ctx(client->ioc, true);
>  
>      trace_nbd_negotiate_begin();
> diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c
> index b69dd982d6..074b4db472 100644
> --- a/scsi/qemu-pr-helper.c
> +++ b/scsi/qemu-pr-helper.c
> @@ -733,8 +733,11 @@ static void coroutine_fn prh_co_entry(void *opaque)
>      uint32_t flags;
>      int r;
>  
> -    qio_channel_set_blocking(QIO_CHANNEL(client->ioc),
> -                             false, NULL);
> +    if (!qio_channel_set_blocking(QIO_CHANNEL(client->ioc),
> +                                  false, &local_err)) {
> +        goto out;
> +    }
> +
>      qio_channel_set_follow_coroutine_ctx(QIO_CHANNEL(client->ioc), true);
>  
>      /* A very simple negotiation for future extensibility.  No features
> @@ -786,6 +789,7 @@ static void coroutine_fn prh_co_entry(void *opaque)
>          }
>      }
>  
> +out:
>      if (local_err) {
>          if (verbose == 0) {
>              error_free(local_err);
> @@ -794,7 +798,6 @@ static void coroutine_fn prh_co_entry(void *opaque)
>          }
>      }
>  
> -out:
>      object_unref(OBJECT(client->ioc));
>      g_free(client);
>  }
> diff --git a/tests/unit/io-channel-helpers.c b/tests/unit/io-channel-helpers.c
> index c0799c21c2..22b42d14cd 100644
> --- a/tests/unit/io-channel-helpers.c
> +++ b/tests/unit/io-channel-helpers.c
> @@ -20,6 +20,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "io-channel-helpers.h"
> +#include "qapi/error.h"
>  #include "qemu/iov.h"
>  
>  struct QIOChannelTest {
> @@ -109,8 +110,8 @@ void qio_channel_test_run_threads(QIOChannelTest *test,
>      test->src = src;
>      test->dst = dst;
>  
> -    qio_channel_set_blocking(test->dst, blocking, NULL);
> -    qio_channel_set_blocking(test->src, blocking, NULL);
> +    qio_channel_set_blocking(test->dst, blocking, &error_abort);
> +    qio_channel_set_blocking(test->src, blocking, &error_abort);
>  
>      reader = g_thread_new("reader",
>                            test_io_thread_reader,
> diff --git a/tests/unit/test-io-channel-tls.c 
> b/tests/unit/test-io-channel-tls.c
> index e036ac5df4..6f282ad45d 100644
> --- a/tests/unit/test-io-channel-tls.c
> +++ b/tests/unit/test-io-channel-tls.c
> @@ -184,8 +184,8 @@ static void test_io_channel_tls(const void *opaque)
>       * thread, so we need these non-blocking to avoid deadlock
>       * of ourselves
>       */
> -    qio_channel_set_blocking(QIO_CHANNEL(clientChanSock), false, NULL);
> -    qio_channel_set_blocking(QIO_CHANNEL(serverChanSock), false, NULL);
> +    qio_channel_set_blocking(QIO_CHANNEL(clientChanSock), false, 
> &error_abort);
> +    qio_channel_set_blocking(QIO_CHANNEL(serverChanSock), false, 
> &error_abort);
>  
>      /* Now the real part of the test, setup the sessions */
>      clientChanTLS = qio_channel_tls_new_client(
> diff --git a/tools/i386/qemu-vmsr-helper.c b/tools/i386/qemu-vmsr-helper.c
> index 5f19a48cbd..6c0f4fe870 100644
> --- a/tools/i386/qemu-vmsr-helper.c
> +++ b/tools/i386/qemu-vmsr-helper.c
> @@ -213,8 +213,10 @@ static void coroutine_fn vh_co_entry(void *opaque)
>      uint64_t vmsr;
>      int r;
>  
> -    qio_channel_set_blocking(QIO_CHANNEL(client->ioc),
> -                             false, NULL);
> +    if (!qio_channel_set_blocking(QIO_CHANNEL(client->ioc),
> +                                  false, &local_err)) {
> +        goto out;
> +    }
>  
>      qio_channel_set_follow_coroutine_ctx(QIO_CHANNEL(client->ioc), true);
>  
> diff --git a/ui/vnc.c b/ui/vnc.c
> index 68ca4a68e7..8ca77b2971 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -3337,7 +3337,7 @@ static void vnc_connect(VncDisplay *vd, 
> QIOChannelSocket *sioc,
>  
>      VNC_DEBUG("New client on socket %p\n", vs->sioc);
>      update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE);
> -    qio_channel_set_blocking(vs->ioc, false, NULL);
> +    qio_channel_set_blocking(vs->ioc, false, &error_abort);
>      if (vs->ioc_tag) {
>          g_source_remove(vs->ioc_tag);
>      }
> diff --git a/util/vhost-user-server.c b/util/vhost-user-server.c
> index b19229074a..d805a92394 100644
> --- a/util/vhost-user-server.c
> +++ b/util/vhost-user-server.c
> @@ -336,6 +336,7 @@ static void vu_accept(QIONetListener *listener, 
> QIOChannelSocket *sioc,
>                        gpointer opaque)
>  {
>      VuServer *server = opaque;
> +    Error *local_err = NULL;
>  
>      if (server->sioc) {
>          warn_report("Only one vhost-user client is allowed to "
> @@ -368,7 +369,11 @@ static void vu_accept(QIONetListener *listener, 
> QIOChannelSocket *sioc,
>      object_ref(OBJECT(server->ioc));
>  
>      /* TODO vu_message_write() spins if non-blocking! */
> -    qio_channel_set_blocking(server->ioc, false, NULL);
> +    if (!qio_channel_set_blocking(server->ioc, false, &local_err)) {
> +        error_report_err(local_err);
> +        vu_deinit(&server->vu_dev);
> +        return;
> +    }
>  
>      qio_channel_set_follow_coroutine_ctx(server->ioc, true);
>  
> -- 
> 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 :|


Reply via email to