* [PATCH v2 0/8] io: deal with blocking/non-blocking fds
@ 2025-09-11 9:19 Vladimir Sementsov-Ogievskiy
2025-09-11 9:19 ` [PATCH v2 1/8] char-socket: tcp_chr_recv(): drop extra _set_(block, cloexec) Vladimir Sementsov-Ogievskiy
` (8 more replies)
0 siblings, 9 replies; 22+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2025-09-11 9:19 UTC (permalink / raw)
To: berrange
Cc: qemu-devel, peterx, qemu-block, vsementsov, leiyang,
marcandre.lureau
Hi all!
The series aims to unify code which sets fds blocking/non-blocking
through the whole source.
01: reworked, only drop the for-loop
02: new
03: - improve commit-message, add a lot of motivation REREAD
- convert GError to Error in a new function
04: - add notes about caller conversion in commit message REREAD
- add r-b by Peter
- save IVSHMEM_SERVER_DEBUG()
- finally decided to keep g_warning() for now: conversion
g_warning() -> g_printerr() should better be another series
and cover the whole code-base (actually not too much, and
mostly in qga)
05: add r-b by Peter
06: new
07: functional part moved to separate commit
08: - fix commit message
- drop redundant qemu/sockets.h includes
v2 is also based on
[PATCH v4 0/2] save qemu-file incoming non-blocking fds
Based-on: <20250910193112.1220763-1-vsementsov@yandex-team.ru>
Vladimir Sementsov-Ogievskiy (8):
char-socket: tcp_chr_recv(): drop extra _set_(block,cloexec)
char-socket: tcp_chr_recv(): add comment
util: add qemu_set_blocking() function
util: drop qemu_socket_set_nonblock()
util: drop qemu_socket_try_set_nonblock()
io/channel-socket: rework qio_channel_socket_copy_fds()
util: drop qemu_socket_set_block()
use qemu_set_blocking instead of g_unix_set_fd_nonblocking
chardev/char-fd.c | 4 +-
chardev/char-pty.c | 3 +-
chardev/char-serial.c | 3 +-
chardev/char-socket.c | 21 ++-----
chardev/char-stdio.c | 3 +-
contrib/ivshmem-server/ivshmem-server.c | 6 +-
hw/hyperv/syndbg.c | 4 +-
hw/input/virtio-input-host.c | 3 +-
hw/misc/ivshmem-flat.c | 3 +-
hw/misc/ivshmem-pci.c | 7 ++-
hw/virtio/vhost-user.c | 5 +-
hw/virtio/vhost-vsock.c | 8 +--
include/qemu/osdep.h | 1 +
include/qemu/sockets.h | 3 -
io/channel-command.c | 9 ++-
io/channel-file.c | 3 +-
io/channel-socket.c | 80 ++++++++++++++++++-------
net/dgram.c | 28 +++++----
net/l2tpv3.c | 5 +-
net/socket.c | 27 ++++++---
net/stream.c | 9 +--
net/stream_data.c | 10 ++--
net/tap-bsd.c | 12 +++-
net/tap-linux.c | 7 ++-
net/tap-solaris.c | 7 ++-
net/tap.c | 21 ++-----
qga/channel-posix.c | 7 ++-
qga/commands-posix.c | 3 +-
tests/qtest/fuzz/virtio_net_fuzz.c | 2 +-
tests/qtest/vhost-user-test.c | 3 +-
tests/unit/socket-helpers.c | 5 +-
tests/unit/test-crypto-tlssession.c | 8 +--
tests/unit/test-iov.c | 5 +-
ui/input-linux.c | 3 +-
util/event_notifier-posix.c | 4 +-
util/main-loop.c | 5 +-
util/oslib-posix.c | 22 ++++---
util/oslib-win32.c | 25 ++++----
util/vhost-user-server.c | 4 +-
39 files changed, 224 insertions(+), 164 deletions(-)
--
2.48.1
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v2 1/8] char-socket: tcp_chr_recv(): drop extra _set_(block, cloexec)
2025-09-11 9:19 [PATCH v2 0/8] io: deal with blocking/non-blocking fds Vladimir Sementsov-Ogievskiy
@ 2025-09-11 9:19 ` Vladimir Sementsov-Ogievskiy
2025-09-12 16:49 ` [PATCH v2 1/8] char-socket: tcp_chr_recv(): drop extra _set_(block,cloexec) Daniel P. Berrangé
2025-09-11 9:20 ` [PATCH v2 2/8] char-socket: tcp_chr_recv(): add comment Vladimir Sementsov-Ogievskiy
` (7 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2025-09-11 9:19 UTC (permalink / raw)
To: berrange
Cc: qemu-devel, peterx, qemu-block, vsementsov, leiyang,
marcandre.lureau, Paolo Bonzini
qio_channel_readv_full() guarantees BLOCKING and CLOEXEC states for
incoming descriptors, no reason to call extra ioctls.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
---
chardev/char-socket.c | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 1e8313915b..b1ce5d01c7 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -307,20 +307,6 @@ static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
s->read_msgfds_num = msgfds_num;
}
- for (i = 0; i < s->read_msgfds_num; i++) {
- int fd = s->read_msgfds[i];
- if (fd < 0) {
- continue;
- }
-
- /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
- qemu_socket_set_block(fd);
-
-#ifndef MSG_CMSG_CLOEXEC
- qemu_set_cloexec(fd);
-#endif
- }
-
if (ret == QIO_CHANNEL_ERR_BLOCK) {
errno = EAGAIN;
ret = -1;
--
2.48.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 2/8] char-socket: tcp_chr_recv(): add comment
2025-09-11 9:19 [PATCH v2 0/8] io: deal with blocking/non-blocking fds Vladimir Sementsov-Ogievskiy
2025-09-11 9:19 ` [PATCH v2 1/8] char-socket: tcp_chr_recv(): drop extra _set_(block, cloexec) Vladimir Sementsov-Ogievskiy
@ 2025-09-11 9:20 ` Vladimir Sementsov-Ogievskiy
2025-09-12 16:50 ` Daniel P. Berrangé
2025-09-11 9:20 ` [PATCH v2 3/8] util: add qemu_set_blocking() function Vladimir Sementsov-Ogievskiy
` (6 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2025-09-11 9:20 UTC (permalink / raw)
To: berrange
Cc: qemu-devel, peterx, qemu-block, vsementsov, leiyang,
marcandre.lureau, Paolo Bonzini
Add comment, to stress that the order of operation (first drop old fds,
second check read status) is intended.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
---
chardev/char-socket.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index b1ce5d01c7..1be078dfc0 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -294,7 +294,12 @@ static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
}
if (msgfds_num) {
- /* close and clean read_msgfds */
+ /*
+ * Close and clean previous read_msgfds, they are obsolete at
+ * this point, regardless result of new call to
+ * qio_channel_readv_full().
+ */
+
for (i = 0; i < s->read_msgfds_num; i++) {
close(s->read_msgfds[i]);
}
--
2.48.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 3/8] util: add qemu_set_blocking() function
2025-09-11 9:19 [PATCH v2 0/8] io: deal with blocking/non-blocking fds Vladimir Sementsov-Ogievskiy
2025-09-11 9:19 ` [PATCH v2 1/8] char-socket: tcp_chr_recv(): drop extra _set_(block, cloexec) Vladimir Sementsov-Ogievskiy
2025-09-11 9:20 ` [PATCH v2 2/8] char-socket: tcp_chr_recv(): add comment Vladimir Sementsov-Ogievskiy
@ 2025-09-11 9:20 ` Vladimir Sementsov-Ogievskiy
2025-09-12 16:51 ` Daniel P. Berrangé
2025-09-11 9:20 ` [PATCH v2 4/8] util: drop qemu_socket_set_nonblock() Vladimir Sementsov-Ogievskiy
` (5 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2025-09-11 9:20 UTC (permalink / raw)
To: berrange
Cc: qemu-devel, peterx, qemu-block, vsementsov, leiyang,
marcandre.lureau, Paolo Bonzini, Stefan Weil
In generic code we have qio_channel_set_blocking(), which takes
bool parameter, and qemu_file_set_blocking(), which as well takes
bool parameter.
At lower fd-layer we have a mess of functions:
- enough direct calls to Unix-specific g_unix_set_fd_nonblocking()
(of course, all calls are out of Windows-compatible code), which
is glib specific with GError, which we can't use, and have to
handle error-reporting by hand after the call.
and several platform-agnostic qemu_* helpers:
- qemu_socket_set_nonblock(), which asserts success for posix (still,
in most cases we can handle the error in better way) and ignores
error for win32 realization
- qemu_socket_try_set_nonblock(), providing and error, but not errp,
so we have to handle it after the call
- qemu_socket_set_block(), which simply ignores an error
Note, that *_socket_* word in original API, which we are going
to substitute was intended, because Windows support these operations
only for sockets. What leads to solution of dropping it again?
1. Having a QEMU-native wrapper with errp parameter
for g_unix_set_fd_nonblocking() for non-socket fds worth doing,
at least to unify error handling.
2. So, if try to keep _socket_ vs _file_ words, we'll have two
actually duplicated functions for Linux, which actually will
be executed successfully on any (good enough) fds, and nothing
prevent using them improperly except for the name. That doesn't
look good.
3. Naming helped us in the world where we crash on errors or
ignore them. Now, with errp parameter, callers are intended to
proper error checking. And for places where we really OK with
crash-on-error semantics (like tests), we have an explicit
&error_abort.
So, this commit starts a series, which will effectively revert
commit ff5927baa7ffb9 "util: rename qemu_*block() socket functions"
(which in turn was reverting f9e8cacc5557e43
"oslib-posix: rename socket_set_nonblock() to qemu_set_nonblock()",
so that's a long story).
Now we don't simply rename, instead we provide the new API and
update all the callers.
This commit only introduces a new fd-layer wrapper. Next commits
will replace old API calls with it, and finally remove old API.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
---
include/qemu/osdep.h | 1 +
util/oslib-posix.c | 15 +++++++++++++++
util/oslib-win32.c | 18 ++++++++++++++++++
3 files changed, 34 insertions(+)
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index be3460b32f..1b38cb7e45 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -687,6 +687,7 @@ ssize_t qemu_write_full(int fd, const void *buf, size_t count)
G_GNUC_WARN_UNUSED_RESULT;
void qemu_set_cloexec(int fd);
+bool qemu_set_blocking(int fd, bool block, Error **errp);
/* Return a dynamically allocated directory path that is appropriate for storing
* local state.
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 4ff577e5de..c737701075 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -250,6 +250,21 @@ void qemu_anon_ram_free(void *ptr, size_t size)
#endif
}
+bool qemu_set_blocking(int fd, bool block, Error **errp)
+{
+ g_autoptr(GError) err = NULL;
+
+ if (!g_unix_set_fd_nonblocking(fd, !block, &err)) {
+ error_setg_errno(errp, errno,
+ "Can't set file descriptor %d %s: %s", fd,
+ block ? "blocking" : "non-blocking",
+ err->message);
+ return false;
+ }
+
+ return true;
+}
+
void qemu_socket_set_block(int fd)
{
g_unix_set_fd_nonblocking(fd, false, NULL);
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index b7351634ec..03044f5b59 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -177,6 +177,24 @@ static int socket_error(void)
}
}
+bool qemu_set_blocking(int fd, bool block, Error **errp)
+{
+ unsigned long opt = block ? 0 : 1;
+
+ if (block) {
+ qemu_socket_unselect(fd, NULL);
+ }
+
+ if (ioctlsocket(fd, FIONBIO, &opt) != NO_ERROR) {
+ error_setg_errno(errp, socket_error(),
+ "Can't set file descriptor %d %s", fd,
+ block ? "blocking" : "non-blocking");
+ return false;
+ }
+
+ return true;
+}
+
void qemu_socket_set_block(int fd)
{
unsigned long opt = 0;
--
2.48.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 4/8] util: drop qemu_socket_set_nonblock()
2025-09-11 9:19 [PATCH v2 0/8] io: deal with blocking/non-blocking fds Vladimir Sementsov-Ogievskiy
` (2 preceding siblings ...)
2025-09-11 9:20 ` [PATCH v2 3/8] util: add qemu_set_blocking() function Vladimir Sementsov-Ogievskiy
@ 2025-09-11 9:20 ` Vladimir Sementsov-Ogievskiy
2025-09-12 16:59 ` Daniel P. Berrangé
2025-09-11 9:20 ` [PATCH v2 5/8] util: drop qemu_socket_try_set_nonblock() Vladimir Sementsov-Ogievskiy
` (4 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2025-09-11 9:20 UTC (permalink / raw)
To: berrange
Cc: qemu-devel, peterx, qemu-block, vsementsov, leiyang,
marcandre.lureau, Michael S. Tsirkin, Stefano Garzarella,
Jason Wang, Michael Roth, Kostiantyn Kostiuk, Paolo Bonzini,
Stefan Weil, Coiby Xu
Use common qemu_set_blocking() instead.
Note that pre-patch the behavior of Win32 and Linux realizations
are inconsistent: we ignore failure for Win32, and assert success
for Linux.
How do we convert the callers?
1. Most of callers call qemu_socket_set_nonblock() on a
freshly created socket fd, in conditions when we may simply
report an error. Seems correct switching to error handling
both for Windows (pre-patch error is ignored) and Linux
(pre-patch we assert success). Anyway, we normally don't
expect errors in these cases.
Still in tests let's use &error_abort for simplicity.
What are exclusions?
2. hw/virtio/vhost-user.c - we are inside #ifdef CONFIG_LINUX,
so no damage in switching to error handling from assertion.
3. io/channel-socket.c: here we convert both old calls to
qemu_socket_set_nonblock() and qemu_socket_set_block() to
one new call. Pre-patch we assert success for Linux in
qemu_socket_set_nonblock(), and ignore all other errors here.
Still, all callers pass errp=NULL to qio_channel_set_blocking(),
so after patch we ignore all errors. Switching from assertion
to ignoring may be not very good, but still acceptable, keeping
in mind that all callers of qio_channel_set_blocking() do
explicitly ignore the error.
4. util/vhost-user-server - compiled only for Linux (see
util/meson.build), so we are safe, switching from assertion to
&error_abort.
Note: In qga/channel-posix.c we use g_warning(), where g_printerr()
would actually be a better choice. Still let's for now follow
common style of qga, where g_warning() is commonly used to print
such messages, and no call to g_printerr(). Converting everything
to use g_printerr() should better be another series.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Peter Xu <peterx@redhat.com>
---
contrib/ivshmem-server/ivshmem-server.c | 6 +++++-
hw/hyperv/syndbg.c | 4 +++-
hw/virtio/vhost-user.c | 5 ++++-
include/qemu/sockets.h | 1 -
io/channel-socket.c | 7 +++----
net/dgram.c | 16 +++++++++++++---
net/l2tpv3.c | 5 +++--
net/socket.c | 20 ++++++++++++++++----
qga/channel-posix.c | 7 ++++++-
tests/unit/socket-helpers.c | 5 ++++-
tests/unit/test-crypto-tlssession.c | 8 ++++----
util/oslib-posix.c | 7 -------
util/oslib-win32.c | 5 -----
util/vhost-user-server.c | 4 ++--
14 files changed, 63 insertions(+), 37 deletions(-)
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index 2f3c7320a6..a65943d0b8 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -146,9 +146,13 @@ ivshmem_server_handle_new_conn(IvshmemServer *server)
return -1;
}
- qemu_socket_set_nonblock(newfd);
IVSHMEM_SERVER_DEBUG(server, "accept()=%d\n", newfd);
+ if (!qemu_set_blocking(newfd, false, NULL)) {
+ close(newfd);
+ return -1;
+ }
+
/* allocate new structure for this peer */
peer = g_malloc0(sizeof(*peer));
peer->sock_fd = newfd;
diff --git a/hw/hyperv/syndbg.c b/hw/hyperv/syndbg.c
index ac7e15f6f1..bcdfdf6af7 100644
--- a/hw/hyperv/syndbg.c
+++ b/hw/hyperv/syndbg.c
@@ -338,7 +338,9 @@ static void hv_syndbg_realize(DeviceState *dev, Error **errp)
return;
}
- qemu_socket_set_nonblock(syndbg->socket);
+ if (!qemu_set_blocking(syndbg->socket, false, errp)) {
+ return;
+ }
syndbg->servaddr.sin_port = htons(syndbg->host_port);
syndbg->servaddr.sin_family = AF_INET;
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 1e1d6b0d6e..36c9c2e04d 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -2039,7 +2039,10 @@ static int vhost_user_postcopy_advise(struct vhost_dev *dev, Error **errp)
error_setg(errp, "%s: Failed to get ufd", __func__);
return -EIO;
}
- qemu_socket_set_nonblock(ufd);
+ if (!qemu_set_blocking(ufd, false, errp)) {
+ close(ufd);
+ return -EINVAL;
+ }
/* register ufd with userfault thread */
u->postcopy_fd.fd = ufd;
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index c562690d89..6477f90b9e 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -48,7 +48,6 @@ int socket_set_cork(int fd, int v);
int socket_set_nodelay(int fd);
void qemu_socket_set_block(int fd);
int qemu_socket_try_set_nonblock(int fd);
-void qemu_socket_set_nonblock(int fd);
int socket_set_fast_reuse(int fd);
#ifdef WIN32
diff --git a/io/channel-socket.c b/io/channel-socket.c
index 21f8f2e0c5..f7e3cb9742 100644
--- a/io/channel-socket.c
+++ b/io/channel-socket.c
@@ -825,11 +825,10 @@ qio_channel_socket_set_blocking(QIOChannel *ioc,
{
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
- if (enabled) {
- qemu_socket_set_block(sioc->fd);
- } else {
- qemu_socket_set_nonblock(sioc->fd);
+ if (!qemu_set_blocking(sioc->fd, enabled, errp)) {
+ return -1;
}
+
return 0;
}
diff --git a/net/dgram.c b/net/dgram.c
index 48f653bceb..fb9ded30df 100644
--- a/net/dgram.c
+++ b/net/dgram.c
@@ -226,7 +226,10 @@ static int net_dgram_mcast_create(struct sockaddr_in *mcastaddr,
}
}
- qemu_socket_set_nonblock(fd);
+ if (!qemu_set_blocking(fd, false, errp)) {
+ goto fail;
+ }
+
return fd;
fail:
if (fd >= 0) {
@@ -504,7 +507,11 @@ int net_init_dgram(const Netdev *netdev, const char *name,
close(fd);
return -1;
}
- qemu_socket_set_nonblock(fd);
+
+ if (!qemu_set_blocking(fd, false, errp)) {
+ close(fd);
+ return -1;
+ }
dest_len = sizeof(raddr_in);
dest_addr = g_malloc(dest_len);
@@ -551,7 +558,10 @@ int net_init_dgram(const Netdev *netdev, const char *name,
close(fd);
return -1;
}
- qemu_socket_set_nonblock(fd);
+ if (!qemu_set_blocking(fd, false, errp)) {
+ close(fd);
+ return -1;
+ }
dest_len = sizeof(raddr_un);
dest_addr = g_malloc(dest_len);
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
index b5547cb917..cdfc641aa6 100644
--- a/net/l2tpv3.c
+++ b/net/l2tpv3.c
@@ -648,6 +648,9 @@ int net_init_l2tpv3(const Netdev *netdev,
error_setg(errp, "could not bind socket err=%i", errno);
goto outerr;
}
+ if (!qemu_set_blocking(fd, false, errp)) {
+ goto outerr;
+ }
freeaddrinfo(result);
@@ -709,8 +712,6 @@ int net_init_l2tpv3(const Netdev *netdev,
s->vec = g_new(struct iovec, MAX_L2TPV3_IOVCNT);
s->header_buf = g_malloc(s->header_size);
- qemu_socket_set_nonblock(fd);
-
s->fd = fd;
s->counter = 0;
diff --git a/net/socket.c b/net/socket.c
index 784dda686f..db25e3d9ae 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -295,7 +295,10 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr,
}
}
- qemu_socket_set_nonblock(fd);
+ if (!qemu_set_blocking(fd, false, errp)) {
+ goto fail;
+ }
+
return fd;
fail:
if (fd >= 0)
@@ -508,7 +511,10 @@ static int net_socket_listen_init(NetClientState *peer,
error_setg_errno(errp, errno, "can't create stream socket");
return -1;
}
- qemu_socket_set_nonblock(fd);
+ if (!qemu_set_blocking(fd, false, errp)) {
+ close(fd);
+ return -1;
+ }
socket_set_fast_reuse(fd);
@@ -556,7 +562,10 @@ static int net_socket_connect_init(NetClientState *peer,
error_setg_errno(errp, errno, "can't create stream socket");
return -1;
}
- qemu_socket_set_nonblock(fd);
+ if (!qemu_set_blocking(fd, false, errp)) {
+ close(fd);
+ return -1;
+ }
connected = 0;
for(;;) {
@@ -671,7 +680,10 @@ static int net_socket_udp_init(NetClientState *peer,
close(fd);
return -1;
}
- qemu_socket_set_nonblock(fd);
+ if (!qemu_set_blocking(fd, false, errp)) {
+ close(fd);
+ return -1;
+ }
s = net_socket_fd_init_dgram(peer, model, name, fd, 0, NULL, errp);
if (!s) {
diff --git a/qga/channel-posix.c b/qga/channel-posix.c
index 465d688ecb..9ccc8b7bd1 100644
--- a/qga/channel-posix.c
+++ b/qga/channel-posix.c
@@ -28,6 +28,7 @@ static gboolean ga_channel_listen_accept(GIOChannel *channel,
GAChannel *c = data;
int ret, client_fd;
bool accepted = false;
+ Error *err = NULL;
g_assert(channel != NULL);
@@ -36,7 +37,11 @@ static gboolean ga_channel_listen_accept(GIOChannel *channel,
g_warning("error converting fd to gsocket: %s", strerror(errno));
goto out;
}
- qemu_socket_set_nonblock(client_fd);
+ if (!qemu_set_blocking(client_fd, false, &err)) {
+ g_warning("%s", error_get_pretty(err));
+ error_free(err);
+ goto out;
+ }
ret = ga_channel_client_add(c, client_fd);
if (ret) {
g_warning("error setting up connection");
diff --git a/tests/unit/socket-helpers.c b/tests/unit/socket-helpers.c
index 37db24f72a..1b7e283f24 100644
--- a/tests/unit/socket-helpers.c
+++ b/tests/unit/socket-helpers.c
@@ -88,7 +88,10 @@ static int socket_can_bind_connect(const char *hostname, int family)
goto cleanup;
}
- qemu_socket_set_nonblock(cfd);
+ if (!qemu_set_blocking(cfd, false, NULL)) {
+ goto cleanup;
+ }
+
if (connect(cfd, (struct sockaddr *)&ss, sslen) < 0) {
if (errno == EINPROGRESS) {
check_soerr = true;
diff --git a/tests/unit/test-crypto-tlssession.c b/tests/unit/test-crypto-tlssession.c
index 554054e934..61311cbe6e 100644
--- a/tests/unit/test-crypto-tlssession.c
+++ b/tests/unit/test-crypto-tlssession.c
@@ -112,8 +112,8 @@ static void test_crypto_tls_session_psk(void)
* thread, so we need these non-blocking to avoid deadlock
* of ourselves
*/
- qemu_socket_set_nonblock(channel[0]);
- qemu_socket_set_nonblock(channel[1]);
+ qemu_set_blocking(channel[0], false, &error_abort);
+ qemu_set_blocking(channel[1], false, &error_abort);
clientCreds = test_tls_creds_psk_create(
QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
@@ -264,8 +264,8 @@ static void test_crypto_tls_session_x509(const void *opaque)
* thread, so we need these non-blocking to avoid deadlock
* of ourselves
*/
- qemu_socket_set_nonblock(channel[0]);
- qemu_socket_set_nonblock(channel[1]);
+ qemu_set_blocking(channel[0], false, &error_abort);
+ qemu_set_blocking(channel[1], false, &error_abort);
#define CLIENT_CERT_DIR "tests/test-crypto-tlssession-client/"
#define SERVER_CERT_DIR "tests/test-crypto-tlssession-server/"
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index c737701075..599993d40d 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -275,13 +275,6 @@ int qemu_socket_try_set_nonblock(int fd)
return g_unix_set_fd_nonblocking(fd, true, NULL) ? 0 : -errno;
}
-void qemu_socket_set_nonblock(int fd)
-{
- int f;
- f = qemu_socket_try_set_nonblock(fd);
- assert(f == 0);
-}
-
int socket_set_fast_reuse(int fd)
{
int val = 1, ret;
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 03044f5b59..1566eb57e7 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -211,11 +211,6 @@ int qemu_socket_try_set_nonblock(int fd)
return 0;
}
-void qemu_socket_set_nonblock(int fd)
-{
- (void)qemu_socket_try_set_nonblock(fd);
-}
-
int socket_set_fast_reuse(int fd)
{
/* Enabling the reuse of an endpoint that was used by a socket still in
diff --git a/util/vhost-user-server.c b/util/vhost-user-server.c
index b19229074a..8dcd32dc65 100644
--- a/util/vhost-user-server.c
+++ b/util/vhost-user-server.c
@@ -78,7 +78,7 @@ static void vmsg_unblock_fds(VhostUserMsg *vmsg)
}
for (i = 0; i < vmsg->fd_num; i++) {
- qemu_socket_set_nonblock(vmsg->fds[i]);
+ qemu_set_blocking(vmsg->fds[i], false, &error_abort);
}
}
@@ -303,7 +303,7 @@ set_watch(VuDev *vu_dev, int fd, int vu_evt,
vu_fd_watch->fd = fd;
vu_fd_watch->cb = cb;
- qemu_socket_set_nonblock(fd);
+ qemu_set_blocking(fd, false, &error_abort);
aio_set_fd_handler(server->ctx, fd, kick_handler,
NULL, NULL, NULL, vu_fd_watch);
vu_fd_watch->vu_dev = vu_dev;
--
2.48.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 5/8] util: drop qemu_socket_try_set_nonblock()
2025-09-11 9:19 [PATCH v2 0/8] io: deal with blocking/non-blocking fds Vladimir Sementsov-Ogievskiy
` (3 preceding siblings ...)
2025-09-11 9:20 ` [PATCH v2 4/8] util: drop qemu_socket_set_nonblock() Vladimir Sementsov-Ogievskiy
@ 2025-09-11 9:20 ` Vladimir Sementsov-Ogievskiy
2025-09-12 17:00 ` Daniel P. Berrangé
2025-09-11 9:20 ` [PATCH v2 6/8] io/channel-socket: rework qio_channel_socket_copy_fds() Vladimir Sementsov-Ogievskiy
` (3 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2025-09-11 9:20 UTC (permalink / raw)
To: berrange
Cc: qemu-devel, peterx, qemu-block, vsementsov, leiyang,
marcandre.lureau, Jason Wang, Paolo Bonzini, Stefan Weil
Now we can use qemu_set_blocking() in these cases.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Peter Xu <peterx@redhat.com>
---
include/qemu/sockets.h | 1 -
net/dgram.c | 12 +++---------
net/socket.c | 7 ++-----
net/stream.c | 9 +++------
net/stream_data.c | 10 ++++------
util/oslib-posix.c | 4 ----
util/oslib-win32.c | 9 ---------
7 files changed, 12 insertions(+), 40 deletions(-)
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 6477f90b9e..9512fec514 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -47,7 +47,6 @@ ssize_t qemu_send_full(int s, const void *buf, size_t count)
int socket_set_cork(int fd, int v);
int socket_set_nodelay(int fd);
void qemu_socket_set_block(int fd);
-int qemu_socket_try_set_nonblock(int fd);
int socket_set_fast_reuse(int fd);
#ifdef WIN32
diff --git a/net/dgram.c b/net/dgram.c
index fb9ded30df..baa126d514 100644
--- a/net/dgram.c
+++ b/net/dgram.c
@@ -287,7 +287,7 @@ static int net_dgram_mcast_init(NetClientState *peer,
Error **errp)
{
NetDgramState *s;
- int fd, ret;
+ int fd;
struct sockaddr_in *saddr;
if (remote->type != SOCKET_ADDRESS_TYPE_INET) {
@@ -335,11 +335,8 @@ static int net_dgram_mcast_init(NetClientState *peer,
g_free(saddr);
return -1;
}
- ret = qemu_socket_try_set_nonblock(fd);
- if (ret < 0) {
+ if (!qemu_set_blocking(fd, false, errp)) {
g_free(saddr);
- error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
- name, fd);
return -1;
}
@@ -572,10 +569,7 @@ int net_init_dgram(const Netdev *netdev, const char *name,
if (fd == -1) {
return -1;
}
- ret = qemu_socket_try_set_nonblock(fd);
- if (ret < 0) {
- error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
- name, fd);
+ if (!qemu_set_blocking(fd, false, errp)) {
return -1;
}
dest_addr = NULL;
diff --git a/net/socket.c b/net/socket.c
index db25e3d9ae..1ad03fc9d4 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -718,7 +718,7 @@ int net_init_socket(const Netdev *netdev, const char *name,
}
if (sock->fd) {
- int fd, ret, so_type;
+ int fd, so_type;
fd = monitor_fd_param(monitor_cur(), sock->fd, errp);
if (fd == -1) {
@@ -728,10 +728,7 @@ int net_init_socket(const Netdev *netdev, const char *name,
if (so_type < 0) {
return -1;
}
- ret = qemu_socket_try_set_nonblock(fd);
- if (ret < 0) {
- error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
- name, fd);
+ if (!qemu_set_blocking(fd, false, errp)) {
return -1;
}
switch (so_type) {
diff --git a/net/stream.c b/net/stream.c
index d893f02cab..94f823a2a7 100644
--- a/net/stream.c
+++ b/net/stream.c
@@ -138,7 +138,6 @@ static void net_stream_server_listening(QIOTask *task, gpointer opaque)
NetStreamData *d = opaque;
QIOChannelSocket *listen_sioc = QIO_CHANNEL_SOCKET(d->listen_ioc);
SocketAddress *addr;
- int ret;
Error *err = NULL;
if (qio_task_propagate_error(task, &err)) {
@@ -149,13 +148,11 @@ static void net_stream_server_listening(QIOTask *task, gpointer opaque)
addr = qio_channel_socket_get_local_address(listen_sioc, NULL);
g_assert(addr != NULL);
- ret = qemu_socket_try_set_nonblock(listen_sioc->fd);
- if (addr->type == SOCKET_ADDRESS_TYPE_FD && ret < 0) {
- qemu_set_info_str(&d->nc, "can't use file descriptor %s (errno %d)",
- addr->u.fd.str, -ret);
+ if (!qemu_set_blocking(listen_sioc->fd, false, &err)) {
+ qemu_set_info_str(&d->nc, "error: %s", error_get_pretty(err));
+ error_free(err);
return;
}
- g_assert(ret == 0);
qapi_free_SocketAddress(addr);
d->nc.link_down = true;
diff --git a/net/stream_data.c b/net/stream_data.c
index 5af27e0d1d..03740e9f73 100644
--- a/net/stream_data.c
+++ b/net/stream_data.c
@@ -12,6 +12,7 @@
#include "net/net.h"
#include "io/channel.h"
#include "io/net-listener.h"
+#include "qemu/sockets.h"
#include "stream_data.h"
@@ -154,7 +155,6 @@ int net_stream_data_client_connected(QIOTask *task, NetStreamData *d)
{
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(d->ioc);
SocketAddress *addr;
- int ret;
Error *err = NULL;
if (qio_task_propagate_error(task, &err)) {
@@ -166,14 +166,12 @@ int net_stream_data_client_connected(QIOTask *task, NetStreamData *d)
addr = qio_channel_socket_get_remote_address(sioc, NULL);
g_assert(addr != NULL);
- ret = qemu_socket_try_set_nonblock(sioc->fd);
- if (addr->type == SOCKET_ADDRESS_TYPE_FD && ret < 0) {
- qemu_set_info_str(&d->nc, "can't use file descriptor %s (errno %d)",
- addr->u.fd.str, -ret);
+ if (!qemu_set_blocking(sioc->fd, false, &err)) {
+ qemu_set_info_str(&d->nc, "error: %s", error_get_pretty(err));
+ error_free(err);
qapi_free_SocketAddress(addr);
goto error;
}
- g_assert(ret == 0);
qapi_free_SocketAddress(addr);
net_socket_rs_init(&d->rs, net_stream_data_rs_finalize, false);
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 599993d40d..7654febfa5 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -270,10 +270,6 @@ void qemu_socket_set_block(int fd)
g_unix_set_fd_nonblocking(fd, false, NULL);
}
-int qemu_socket_try_set_nonblock(int fd)
-{
- return g_unix_set_fd_nonblocking(fd, true, NULL) ? 0 : -errno;
-}
int socket_set_fast_reuse(int fd)
{
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 1566eb57e7..bf5d478c5c 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -202,15 +202,6 @@ void qemu_socket_set_block(int fd)
ioctlsocket(fd, FIONBIO, &opt);
}
-int qemu_socket_try_set_nonblock(int fd)
-{
- unsigned long opt = 1;
- if (ioctlsocket(fd, FIONBIO, &opt) != NO_ERROR) {
- return -socket_error();
- }
- return 0;
-}
-
int socket_set_fast_reuse(int fd)
{
/* Enabling the reuse of an endpoint that was used by a socket still in
--
2.48.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 6/8] io/channel-socket: rework qio_channel_socket_copy_fds()
2025-09-11 9:19 [PATCH v2 0/8] io: deal with blocking/non-blocking fds Vladimir Sementsov-Ogievskiy
` (4 preceding siblings ...)
2025-09-11 9:20 ` [PATCH v2 5/8] util: drop qemu_socket_try_set_nonblock() Vladimir Sementsov-Ogievskiy
@ 2025-09-11 9:20 ` Vladimir Sementsov-Ogievskiy
2025-09-12 17:05 ` Daniel P. Berrangé
2025-09-11 9:20 ` [PATCH v2 7/8] util: drop qemu_socket_set_block() Vladimir Sementsov-Ogievskiy
` (2 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2025-09-11 9:20 UTC (permalink / raw)
To: berrange
Cc: qemu-devel, peterx, qemu-block, vsementsov, leiyang,
marcandre.lureau
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 <vsementsov@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)
+{
+ int *end = fds + nfds, *fd;
+
+ for (fd = fds; fd != end; fd++) {
+ if (*fd < 0) {
+ continue;
}
- *nfds += gotfds;
+ close(*fd);
}
+
+ g_free(fds);
}
@@ -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;
}
return ret;
--
2.48.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 7/8] util: drop qemu_socket_set_block()
2025-09-11 9:19 [PATCH v2 0/8] io: deal with blocking/non-blocking fds Vladimir Sementsov-Ogievskiy
` (5 preceding siblings ...)
2025-09-11 9:20 ` [PATCH v2 6/8] io/channel-socket: rework qio_channel_socket_copy_fds() Vladimir Sementsov-Ogievskiy
@ 2025-09-11 9:20 ` Vladimir Sementsov-Ogievskiy
2025-09-12 17:06 ` Daniel P. Berrangé
2025-09-11 9:20 ` [PATCH v2 8/8] use qemu_set_blocking instead of g_unix_set_fd_nonblocking Vladimir Sementsov-Ogievskiy
2025-09-11 9:22 ` [PATCH v2 0/8] io: deal with blocking/non-blocking fds Vladimir Sementsov-Ogievskiy
8 siblings, 1 reply; 22+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2025-09-11 9:20 UTC (permalink / raw)
To: berrange
Cc: qemu-devel, peterx, qemu-block, vsementsov, leiyang,
marcandre.lureau, Paolo Bonzini, Stefan Weil
Now it's unused.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
---
include/qemu/sockets.h | 1 -
util/oslib-posix.c | 6 ------
util/oslib-win32.c | 7 -------
3 files changed, 14 deletions(-)
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 9512fec514..be351d85f7 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -46,7 +46,6 @@ ssize_t qemu_send_full(int s, const void *buf, size_t count)
G_GNUC_WARN_UNUSED_RESULT;
int socket_set_cork(int fd, int v);
int socket_set_nodelay(int fd);
-void qemu_socket_set_block(int fd);
int socket_set_fast_reuse(int fd);
#ifdef WIN32
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 7654febfa5..14cf94ac03 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -265,12 +265,6 @@ bool qemu_set_blocking(int fd, bool block, Error **errp)
return true;
}
-void qemu_socket_set_block(int fd)
-{
- g_unix_set_fd_nonblocking(fd, false, NULL);
-}
-
-
int socket_set_fast_reuse(int fd)
{
int val = 1, ret;
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index bf5d478c5c..b9ce2f96ee 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -195,13 +195,6 @@ bool qemu_set_blocking(int fd, bool block, Error **errp)
return true;
}
-void qemu_socket_set_block(int fd)
-{
- unsigned long opt = 0;
- qemu_socket_unselect(fd, NULL);
- ioctlsocket(fd, FIONBIO, &opt);
-}
-
int socket_set_fast_reuse(int fd)
{
/* Enabling the reuse of an endpoint that was used by a socket still in
--
2.48.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 8/8] use qemu_set_blocking instead of g_unix_set_fd_nonblocking
2025-09-11 9:19 [PATCH v2 0/8] io: deal with blocking/non-blocking fds Vladimir Sementsov-Ogievskiy
` (6 preceding siblings ...)
2025-09-11 9:20 ` [PATCH v2 7/8] util: drop qemu_socket_set_block() Vladimir Sementsov-Ogievskiy
@ 2025-09-11 9:20 ` Vladimir Sementsov-Ogievskiy
2025-09-12 17:11 ` Daniel P. Berrangé
2025-09-11 9:22 ` [PATCH v2 0/8] io: deal with blocking/non-blocking fds Vladimir Sementsov-Ogievskiy
8 siblings, 1 reply; 22+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2025-09-11 9:20 UTC (permalink / raw)
To: berrange
Cc: qemu-devel, peterx, qemu-block, vsementsov, leiyang,
marcandre.lureau, Paolo Bonzini, Michael S. Tsirkin,
Gerd Hoffmann, Gustavo Romero, Stefano Garzarella, Jason Wang,
Michael Roth, Kostiantyn Kostiuk, Alexander Bulekov, Bandan Das,
Stefan Hajnoczi, Fabiano Rosas, Darren Kenny, Qiuhao Li,
Laurent Vivier
Instead of open-coded g_unix_set_fd_nonblocking() calls, use
QEMU wrapper qemu_set_blocking().
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
---
chardev/char-fd.c | 4 ++--
chardev/char-pty.c | 3 +--
chardev/char-serial.c | 3 +--
chardev/char-stdio.c | 3 +--
hw/input/virtio-input-host.c | 3 +--
hw/misc/ivshmem-flat.c | 3 ++-
hw/misc/ivshmem-pci.c | 7 ++++++-
hw/virtio/vhost-vsock.c | 8 ++------
io/channel-command.c | 9 ++++++---
io/channel-file.c | 3 +--
net/tap-bsd.c | 12 ++++++++++--
net/tap-linux.c | 7 ++++++-
net/tap-solaris.c | 7 ++++++-
net/tap.c | 21 ++++++---------------
qga/commands-posix.c | 3 +--
tests/qtest/fuzz/virtio_net_fuzz.c | 2 +-
tests/qtest/vhost-user-test.c | 3 +--
tests/unit/test-iov.c | 5 +++--
ui/input-linux.c | 3 +--
util/event_notifier-posix.c | 4 ++--
util/main-loop.c | 5 ++++-
21 files changed, 64 insertions(+), 54 deletions(-)
diff --git a/chardev/char-fd.c b/chardev/char-fd.c
index 6f03adf872..739dc68c36 100644
--- a/chardev/char-fd.c
+++ b/chardev/char-fd.c
@@ -212,8 +212,8 @@ void qemu_chr_open_fd(Chardev *chr,
FDChardev *s = FD_CHARDEV(chr);
g_autofree char *name = NULL;
- if (fd_out >= 0 && !g_unix_set_fd_nonblocking(fd_out, true, NULL)) {
- assert(!"Failed to set FD nonblocking");
+ if (fd_out >= 0) {
+ qemu_set_blocking(fd_out, false, &error_abort);
}
if (fd_out == fd_in && fd_in >= 0) {
diff --git a/chardev/char-pty.c b/chardev/char-pty.c
index 674e9b3f14..fe6bfb043d 100644
--- a/chardev/char-pty.c
+++ b/chardev/char-pty.c
@@ -349,8 +349,7 @@ static void char_pty_open(Chardev *chr,
}
close(slave_fd);
- if (!g_unix_set_fd_nonblocking(master_fd, true, NULL)) {
- error_setg_errno(errp, errno, "Failed to set FD nonblocking");
+ if (!qemu_set_blocking(master_fd, false, errp)) {
return;
}
diff --git a/chardev/char-serial.c b/chardev/char-serial.c
index 0a68b4b4e0..1ff31dcde3 100644
--- a/chardev/char-serial.c
+++ b/chardev/char-serial.c
@@ -271,8 +271,7 @@ static void qmp_chardev_open_serial(Chardev *chr,
if (fd < 0) {
return;
}
- if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
- error_setg_errno(errp, errno, "Failed to set FD nonblocking");
+ if (!qemu_set_blocking(fd, false, errp)) {
return;
}
tty_serial_init(fd, 115200, 'N', 8, 1);
diff --git a/chardev/char-stdio.c b/chardev/char-stdio.c
index 48db8d2f30..193727e807 100644
--- a/chardev/char-stdio.c
+++ b/chardev/char-stdio.c
@@ -107,8 +107,7 @@ static void qemu_chr_open_stdio(Chardev *chr,
old_fd0_flags = fcntl(0, F_GETFL);
old_fd1_flags = fcntl(1, F_GETFL);
tcgetattr(0, &oldtty);
- if (!g_unix_set_fd_nonblocking(0, true, NULL)) {
- error_setg_errno(errp, errno, "Failed to set FD nonblocking");
+ if (!qemu_set_blocking(0, false, errp)) {
return;
}
atexit(term_exit);
diff --git a/hw/input/virtio-input-host.c b/hw/input/virtio-input-host.c
index bbfee9d3b9..9f62532559 100644
--- a/hw/input/virtio-input-host.c
+++ b/hw/input/virtio-input-host.c
@@ -114,8 +114,7 @@ static void virtio_input_host_realize(DeviceState *dev, Error **errp)
error_setg_file_open(errp, errno, vih->evdev);
return;
}
- if (!g_unix_set_fd_nonblocking(vih->fd, true, NULL)) {
- error_setg_errno(errp, errno, "Failed to set FD nonblocking");
+ if (!qemu_set_blocking(vih->fd, false, errp)) {
goto err_close;
}
diff --git a/hw/misc/ivshmem-flat.c b/hw/misc/ivshmem-flat.c
index fe4be6be17..89495f6a11 100644
--- a/hw/misc/ivshmem-flat.c
+++ b/hw/misc/ivshmem-flat.c
@@ -154,7 +154,8 @@ static void ivshmem_flat_add_vector(IvshmemFTState *s, IvshmemPeer *peer,
* peer.
*/
peer->vector[peer->vector_counter].id = peer->vector_counter;
- g_unix_set_fd_nonblocking(vector_fd, true, NULL);
+ /* WARNING: qemu_socket_set_nonblock() return code ignored */
+ qemu_set_blocking(vector_fd, false, NULL);
event_notifier_init_fd(&peer->vector[peer->vector_counter].event_notifier,
vector_fd);
diff --git a/hw/misc/ivshmem-pci.c b/hw/misc/ivshmem-pci.c
index d47ae739d6..2748db9286 100644
--- a/hw/misc/ivshmem-pci.c
+++ b/hw/misc/ivshmem-pci.c
@@ -540,7 +540,12 @@ static void process_msg_connect(IVShmemState *s, uint16_t posn, int fd,
IVSHMEM_DPRINTF("eventfds[%d][%d] = %d\n", posn, vector, fd);
event_notifier_init_fd(&peer->eventfds[vector], fd);
- g_unix_set_fd_nonblocking(fd, true, NULL); /* msix/irqfd poll non block */
+
+ /* msix/irqfd poll non block */
+ if (!qemu_set_blocking(fd, false, errp)) {
+ close(fd);
+ return;
+ }
if (posn == s->vm_id) {
setup_interrupt(s, vector, errp);
diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c
index 6e4088831f..107d88babe 100644
--- a/hw/virtio/vhost-vsock.c
+++ b/hw/virtio/vhost-vsock.c
@@ -147,9 +147,7 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp)
return;
}
- if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) {
- error_setg_errno(errp, errno,
- "vhost-vsock: unable to set non-blocking mode");
+ if (!qemu_set_blocking(vhostfd, false, errp)) {
return;
}
} else {
@@ -160,9 +158,7 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp)
return;
}
- if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) {
- error_setg_errno(errp, errno,
- "Failed to set FD nonblocking");
+ if (!qemu_set_blocking(vhostfd, false, errp)) {
return;
}
}
diff --git a/io/channel-command.c b/io/channel-command.c
index 8966dd3a2b..8ae9a026b3 100644
--- a/io/channel-command.c
+++ b/io/channel-command.c
@@ -277,9 +277,12 @@ static int qio_channel_command_set_blocking(QIOChannel *ioc,
cioc->blocking = enabled;
#else
- if ((cioc->writefd >= 0 && !g_unix_set_fd_nonblocking(cioc->writefd, !enabled, NULL)) ||
- (cioc->readfd >= 0 && !g_unix_set_fd_nonblocking(cioc->readfd, !enabled, NULL))) {
- error_setg_errno(errp, errno, "Failed to set FD nonblocking");
+ if (cioc->writefd >= 0 &&
+ !qemu_set_blocking(cioc->writefd, enabled, errp)) {
+ return -1;
+ }
+ if (cioc->readfd >= 0 &&
+ !qemu_set_blocking(cioc->readfd, enabled, errp)) {
return -1;
}
#endif
diff --git a/io/channel-file.c b/io/channel-file.c
index ca3f180cc2..5cef75a67c 100644
--- a/io/channel-file.c
+++ b/io/channel-file.c
@@ -223,8 +223,7 @@ static int qio_channel_file_set_blocking(QIOChannel *ioc,
#else
QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
- if (!g_unix_set_fd_nonblocking(fioc->fd, !enabled, NULL)) {
- error_setg_errno(errp, errno, "Failed to set FD nonblocking");
+ if (!qemu_set_blocking(fioc->fd, enabled, errp)) {
return -1;
}
return 0;
diff --git a/net/tap-bsd.c b/net/tap-bsd.c
index b4c84441ba..2e444e59b5 100644
--- a/net/tap-bsd.c
+++ b/net/tap-bsd.c
@@ -98,7 +98,12 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
return -1;
}
}
- g_unix_set_fd_nonblocking(fd, true, NULL);
+
+ if (!qemu_set_blocking(fd, false, errp) {
+ close(fd);
+ return -1;
+ }
+
return fd;
}
@@ -189,7 +194,10 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
goto error;
}
- g_unix_set_fd_nonblocking(fd, true, NULL);
+ if (!qemu_set_blocking(fd, false, errp) {
+ goto error;
+ }
+
return fd;
error:
diff --git a/net/tap-linux.c b/net/tap-linux.c
index 22ec2f45d2..981ef838fb 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -124,7 +124,12 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
return -1;
}
pstrcpy(ifname, ifname_size, ifr.ifr_name);
- g_unix_set_fd_nonblocking(fd, true, NULL);
+
+ if (!qemu_set_blocking(fd, false, NULL)) {
+ close(fd);
+ return -1;
+ }
+
return fd;
}
diff --git a/net/tap-solaris.c b/net/tap-solaris.c
index 51b7830bef..02709590c1 100644
--- a/net/tap-solaris.c
+++ b/net/tap-solaris.c
@@ -198,7 +198,12 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
return -1;
}
}
- g_unix_set_fd_nonblocking(fd, true, NULL);
+
+ if (!qemu_set_blocking(fd, false NULL)) {
+ close(fd);
+ return -1;
+ }
+
return fd;
}
diff --git a/net/tap.c b/net/tap.c
index f7df702f97..f37133e301 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -627,8 +627,7 @@ int net_init_bridge(const Netdev *netdev, const char *name,
return -1;
}
- if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
- error_setg_errno(errp, errno, "Failed to set FD nonblocking");
+ if (!qemu_set_blocking(fd, false, errp)) {
return -1;
}
vnet_hdr = tap_probe_vnet_hdr(fd, errp);
@@ -729,9 +728,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
error_propagate(errp, err);
goto failed;
}
- if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) {
- error_setg_errno(errp, errno, "%s: Can't use file descriptor %d",
- name, fd);
+ if (!qemu_set_blocking(vhostfd, false, errp)) {
goto failed;
}
} else {
@@ -741,8 +738,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
"tap: open vhost char device failed");
goto failed;
}
- if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) {
- error_setg_errno(errp, errno, "Failed to set FD nonblocking");
+ if (!qemu_set_blocking(vhostfd, false, errp)) {
goto failed;
}
}
@@ -839,9 +835,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
return -1;
}
- if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
- error_setg_errno(errp, errno, "%s: Can't use file descriptor %d",
- name, fd);
+ if (!qemu_set_blocking(fd, false, errp)) {
close(fd);
return -1;
}
@@ -895,10 +889,8 @@ int net_init_tap(const Netdev *netdev, const char *name,
goto free_fail;
}
- if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
+ if (!qemu_set_blocking(fd, false, errp)) {
ret = -1;
- error_setg_errno(errp, errno, "%s: Can't use file descriptor %d",
- name, fd);
goto free_fail;
}
@@ -951,8 +943,7 @@ free_fail:
return -1;
}
- if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
- error_setg_errno(errp, errno, "Failed to set FD nonblocking");
+ if (!qemu_set_blocking(fd, false, errp)) {
return -1;
}
vnet_hdr = tap_probe_vnet_hdr(fd, errp);
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 12bc086d79..5070f27d75 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -503,9 +503,8 @@ int64_t qmp_guest_file_open(const char *path, const char *mode,
/* set fd non-blocking to avoid common use cases (like reading from a
* named pipe) from hanging the agent
*/
- if (!g_unix_set_fd_nonblocking(fileno(fh), true, NULL)) {
+ if (!qemu_set_blocking(fileno(fh), false, errp)) {
fclose(fh);
- error_setg_errno(errp, errno, "Failed to set FD nonblocking");
return -1;
}
diff --git a/tests/qtest/fuzz/virtio_net_fuzz.c b/tests/qtest/fuzz/virtio_net_fuzz.c
index e239875e3b..e9b13d3e4f 100644
--- a/tests/qtest/fuzz/virtio_net_fuzz.c
+++ b/tests/qtest/fuzz/virtio_net_fuzz.c
@@ -132,7 +132,7 @@ static void *virtio_net_test_setup_socket(GString *cmd_line, void *arg)
{
int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sockfds);
g_assert_cmpint(ret, !=, -1);
- g_unix_set_fd_nonblocking(sockfds[0], true, NULL);
+ qemu_set_blocking(sockfds[0], false, &error_abort);
sockfds_initialized = true;
g_string_append_printf(cmd_line, " -netdev socket,fd=%d,id=hs0 ",
sockfds[1]);
diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c
index 56472ca709..e39d6e7787 100644
--- a/tests/qtest/vhost-user-test.c
+++ b/tests/qtest/vhost-user-test.c
@@ -471,8 +471,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
* The receive function forces it to be blocking,
* so revert it back to non-blocking.
*/
- g_unix_set_fd_nonblocking(fd, true, &err);
- g_assert_no_error(err);
+ qemu_set_blocking(fd, false, &error_abort);
break;
case VHOST_USER_SET_LOG_BASE:
diff --git a/tests/unit/test-iov.c b/tests/unit/test-iov.c
index 75bc3be005..63e2b1583c 100644
--- a/tests/unit/test-iov.c
+++ b/tests/unit/test-iov.c
@@ -1,4 +1,5 @@
#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qemu/iov.h"
#include "qemu/sockets.h"
@@ -186,7 +187,7 @@ static void test_io(void)
close(sv[0]);
FD_SET(sv[1], &fds);
- g_unix_set_fd_nonblocking(sv[1], true, NULL);
+ qemu_set_blocking(sv[1], false, &error_abort);
r = g_test_rand_int_range(sz / 2, sz);
setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &r, sizeof(r));
@@ -222,7 +223,7 @@ static void test_io(void)
close(sv[1]);
FD_SET(sv[0], &fds);
- g_unix_set_fd_nonblocking(sv[0], true, NULL);
+ qemu_set_blocking(sv[0], false, &error_abort);
r = g_test_rand_int_range(sz / 2, sz);
setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r));
usleep(500000);
diff --git a/ui/input-linux.c b/ui/input-linux.c
index 92e1a1aa64..44d0c15a9b 100644
--- a/ui/input-linux.c
+++ b/ui/input-linux.c
@@ -316,8 +316,7 @@ static void input_linux_complete(UserCreatable *uc, Error **errp)
error_setg_file_open(errp, errno, il->evdev);
return;
}
- if (!g_unix_set_fd_nonblocking(il->fd, true, NULL)) {
- error_setg_errno(errp, errno, "Failed to set FD nonblocking");
+ if (!qemu_set_blocking(il->fd, false, errp)) {
return;
}
diff --git a/util/event_notifier-posix.c b/util/event_notifier-posix.c
index 76420c5b56..9952de63dd 100644
--- a/util/event_notifier-posix.c
+++ b/util/event_notifier-posix.c
@@ -52,11 +52,11 @@ int event_notifier_init(EventNotifier *e, int active)
if (!g_unix_open_pipe(fds, FD_CLOEXEC, NULL)) {
return -errno;
}
- if (!g_unix_set_fd_nonblocking(fds[0], true, NULL)) {
+ if (!qemu_set_blocking(fds[0], false, NULL)) {
ret = -errno;
goto fail;
}
- if (!g_unix_set_fd_nonblocking(fds[1], true, NULL)) {
+ if (!qemu_set_blocking(fds[1], false, NULL)) {
ret = -errno;
goto fail;
}
diff --git a/util/main-loop.c b/util/main-loop.c
index 51aeb2432e..b8ddda8f5e 100644
--- a/util/main-loop.c
+++ b/util/main-loop.c
@@ -114,7 +114,10 @@ static int qemu_signal_init(Error **errp)
return -errno;
}
- g_unix_set_fd_nonblocking(sigfd, true, NULL);
+ if (!qemu_set_blocking(sigfd, false, errp)) {
+ close(sigfd);
+ return -EINVAL;
+ }
qemu_set_fd_handler(sigfd, sigfd_handler, NULL, (void *)(intptr_t)sigfd);
--
2.48.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v2 0/8] io: deal with blocking/non-blocking fds
2025-09-11 9:19 [PATCH v2 0/8] io: deal with blocking/non-blocking fds Vladimir Sementsov-Ogievskiy
` (7 preceding siblings ...)
2025-09-11 9:20 ` [PATCH v2 8/8] use qemu_set_blocking instead of g_unix_set_fd_nonblocking Vladimir Sementsov-Ogievskiy
@ 2025-09-11 9:22 ` Vladimir Sementsov-Ogievskiy
8 siblings, 0 replies; 22+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2025-09-11 9:22 UTC (permalink / raw)
To: berrange; +Cc: qemu-devel, peterx, qemu-block, leiyang, marcandre.lureau
On 11.09.25 12:19, Vladimir Sementsov-Ogievskiy wrote:
> Hi all!
>
> The series aims to unify code which sets fds blocking/non-blocking
> through the whole source.
>
> 01: reworked, only drop the for-loop
> 02: new
> 03: - improve commit-message, add a lot of motivation REREAD
> - convert GError to Error in a new function
> 04: - add notes about caller conversion in commit message REREAD
REREAD - was notes for myself :)
> - add r-b by Peter
> - save IVSHMEM_SERVER_DEBUG()
> - finally decided to keep g_warning() for now: conversion
> g_warning() -> g_printerr() should better be another series
> and cover the whole code-base (actually not too much, and
> mostly in qga)
> 05: add r-b by Peter
> 06: new
> 07: functional part moved to separate commit
> 08: - fix commit message
> - drop redundant qemu/sockets.h includes
>
> v2 is also based on
> [PATCH v4 0/2] save qemu-file incoming non-blocking fds
> Based-on: <20250910193112.1220763-1-vsementsov@yandex-team.ru>
>
> Vladimir Sementsov-Ogievskiy (8):
> char-socket: tcp_chr_recv(): drop extra _set_(block,cloexec)
> char-socket: tcp_chr_recv(): add comment
> util: add qemu_set_blocking() function
> util: drop qemu_socket_set_nonblock()
> util: drop qemu_socket_try_set_nonblock()
> io/channel-socket: rework qio_channel_socket_copy_fds()
> util: drop qemu_socket_set_block()
> use qemu_set_blocking instead of g_unix_set_fd_nonblocking
>
> chardev/char-fd.c | 4 +-
> chardev/char-pty.c | 3 +-
> chardev/char-serial.c | 3 +-
> chardev/char-socket.c | 21 ++-----
> chardev/char-stdio.c | 3 +-
> contrib/ivshmem-server/ivshmem-server.c | 6 +-
> hw/hyperv/syndbg.c | 4 +-
> hw/input/virtio-input-host.c | 3 +-
> hw/misc/ivshmem-flat.c | 3 +-
> hw/misc/ivshmem-pci.c | 7 ++-
> hw/virtio/vhost-user.c | 5 +-
> hw/virtio/vhost-vsock.c | 8 +--
> include/qemu/osdep.h | 1 +
> include/qemu/sockets.h | 3 -
> io/channel-command.c | 9 ++-
> io/channel-file.c | 3 +-
> io/channel-socket.c | 80 ++++++++++++++++++-------
> net/dgram.c | 28 +++++----
> net/l2tpv3.c | 5 +-
> net/socket.c | 27 ++++++---
> net/stream.c | 9 +--
> net/stream_data.c | 10 ++--
> net/tap-bsd.c | 12 +++-
> net/tap-linux.c | 7 ++-
> net/tap-solaris.c | 7 ++-
> net/tap.c | 21 ++-----
> qga/channel-posix.c | 7 ++-
> qga/commands-posix.c | 3 +-
> tests/qtest/fuzz/virtio_net_fuzz.c | 2 +-
> tests/qtest/vhost-user-test.c | 3 +-
> tests/unit/socket-helpers.c | 5 +-
> tests/unit/test-crypto-tlssession.c | 8 +--
> tests/unit/test-iov.c | 5 +-
> ui/input-linux.c | 3 +-
> util/event_notifier-posix.c | 4 +-
> util/main-loop.c | 5 +-
> util/oslib-posix.c | 22 ++++---
> util/oslib-win32.c | 25 ++++----
> util/vhost-user-server.c | 4 +-
> 39 files changed, 224 insertions(+), 164 deletions(-)
>
--
Best regards,
Vladimir
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 1/8] char-socket: tcp_chr_recv(): drop extra _set_(block,cloexec)
2025-09-11 9:19 ` [PATCH v2 1/8] char-socket: tcp_chr_recv(): drop extra _set_(block, cloexec) Vladimir Sementsov-Ogievskiy
@ 2025-09-12 16:49 ` Daniel P. Berrangé
0 siblings, 0 replies; 22+ messages in thread
From: Daniel P. Berrangé @ 2025-09-12 16:49 UTC (permalink / raw)
To: Vladimir Sementsov-Ogievskiy
Cc: qemu-devel, peterx, qemu-block, leiyang, marcandre.lureau,
Paolo Bonzini
On Thu, Sep 11, 2025 at 12:19:59PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> qio_channel_readv_full() guarantees BLOCKING and CLOEXEC states for
> incoming descriptors, no reason to call extra ioctls.
>
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
> ---
> chardev/char-socket.c | 14 --------------
> 1 file changed, 14 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
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 :|
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 2/8] char-socket: tcp_chr_recv(): add comment
2025-09-11 9:20 ` [PATCH v2 2/8] char-socket: tcp_chr_recv(): add comment Vladimir Sementsov-Ogievskiy
@ 2025-09-12 16:50 ` Daniel P. Berrangé
0 siblings, 0 replies; 22+ messages in thread
From: Daniel P. Berrangé @ 2025-09-12 16:50 UTC (permalink / raw)
To: Vladimir Sementsov-Ogievskiy
Cc: qemu-devel, peterx, qemu-block, leiyang, marcandre.lureau,
Paolo Bonzini
On Thu, Sep 11, 2025 at 12:20:00PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> Add comment, to stress that the order of operation (first drop old fds,
> second check read status) is intended.
>
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
> ---
> chardev/char-socket.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
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 :|
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 3/8] util: add qemu_set_blocking() function
2025-09-11 9:20 ` [PATCH v2 3/8] util: add qemu_set_blocking() function Vladimir Sementsov-Ogievskiy
@ 2025-09-12 16:51 ` Daniel P. Berrangé
0 siblings, 0 replies; 22+ messages in thread
From: Daniel P. Berrangé @ 2025-09-12 16:51 UTC (permalink / raw)
To: Vladimir Sementsov-Ogievskiy
Cc: qemu-devel, peterx, qemu-block, leiyang, marcandre.lureau,
Paolo Bonzini, Stefan Weil
On Thu, Sep 11, 2025 at 12:20:01PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> In generic code we have qio_channel_set_blocking(), which takes
> bool parameter, and qemu_file_set_blocking(), which as well takes
> bool parameter.
>
> At lower fd-layer we have a mess of functions:
>
> - enough direct calls to Unix-specific g_unix_set_fd_nonblocking()
> (of course, all calls are out of Windows-compatible code), which
> is glib specific with GError, which we can't use, and have to
> handle error-reporting by hand after the call.
>
> and several platform-agnostic qemu_* helpers:
>
> - qemu_socket_set_nonblock(), which asserts success for posix (still,
> in most cases we can handle the error in better way) and ignores
> error for win32 realization
>
> - qemu_socket_try_set_nonblock(), providing and error, but not errp,
> so we have to handle it after the call
>
> - qemu_socket_set_block(), which simply ignores an error
>
> Note, that *_socket_* word in original API, which we are going
> to substitute was intended, because Windows support these operations
> only for sockets. What leads to solution of dropping it again?
>
> 1. Having a QEMU-native wrapper with errp parameter
> for g_unix_set_fd_nonblocking() for non-socket fds worth doing,
> at least to unify error handling.
>
> 2. So, if try to keep _socket_ vs _file_ words, we'll have two
> actually duplicated functions for Linux, which actually will
> be executed successfully on any (good enough) fds, and nothing
> prevent using them improperly except for the name. That doesn't
> look good.
>
> 3. Naming helped us in the world where we crash on errors or
> ignore them. Now, with errp parameter, callers are intended to
> proper error checking. And for places where we really OK with
> crash-on-error semantics (like tests), we have an explicit
> &error_abort.
>
> So, this commit starts a series, which will effectively revert
> commit ff5927baa7ffb9 "util: rename qemu_*block() socket functions"
> (which in turn was reverting f9e8cacc5557e43
> "oslib-posix: rename socket_set_nonblock() to qemu_set_nonblock()",
> so that's a long story).
> Now we don't simply rename, instead we provide the new API and
> update all the callers.
>
> This commit only introduces a new fd-layer wrapper. Next commits
> will replace old API calls with it, and finally remove old API.
>
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
> ---
> include/qemu/osdep.h | 1 +
> util/oslib-posix.c | 15 +++++++++++++++
> util/oslib-win32.c | 18 ++++++++++++++++++
> 3 files changed, 34 insertions(+)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
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 :|
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 4/8] util: drop qemu_socket_set_nonblock()
2025-09-11 9:20 ` [PATCH v2 4/8] util: drop qemu_socket_set_nonblock() Vladimir Sementsov-Ogievskiy
@ 2025-09-12 16:59 ` Daniel P. Berrangé
2025-09-15 8:07 ` Vladimir Sementsov-Ogievskiy
2025-09-15 8:09 ` Vladimir Sementsov-Ogievskiy
0 siblings, 2 replies; 22+ messages in thread
From: Daniel P. Berrangé @ 2025-09-12 16:59 UTC (permalink / raw)
To: Vladimir Sementsov-Ogievskiy
Cc: qemu-devel, peterx, qemu-block, leiyang, marcandre.lureau,
Michael S. Tsirkin, Stefano Garzarella, Jason Wang, Michael Roth,
Kostiantyn Kostiuk, Paolo Bonzini, Stefan Weil, Coiby Xu
On Thu, Sep 11, 2025 at 12:20:02PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> Use common qemu_set_blocking() instead.
>
> Note that pre-patch the behavior of Win32 and Linux realizations
> are inconsistent: we ignore failure for Win32, and assert success
> for Linux.
>
> How do we convert the callers?
> 3. io/channel-socket.c: here we convert both old calls to
> qemu_socket_set_nonblock() and qemu_socket_set_block() to
> one new call. Pre-patch we assert success for Linux in
> qemu_socket_set_nonblock(), and ignore all other errors here.
> Still, all callers pass errp=NULL to qio_channel_set_blocking(),
> so after patch we ignore all errors. Switching from assertion
> to ignoring may be not very good, but still acceptable, keeping
> in mind that all callers of qio_channel_set_blocking() do
> explicitly ignore the error.
This is a bit questionable. IMHO the reason why nearly all
callers pass errp=NULL is laziness based on the assumption
that the code actually asserts, and no one thinking to check
the win impl which didn't asset.
IOW, I think we need a prior patch that sets the 'errp'
in all these callers, either to &error_abort, or to
propage the error if practical.
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
> Reviewed-by: Peter Xu <peterx@redhat.com>
> ---
> contrib/ivshmem-server/ivshmem-server.c | 6 +++++-
> hw/hyperv/syndbg.c | 4 +++-
> hw/virtio/vhost-user.c | 5 ++++-
> include/qemu/sockets.h | 1 -
> io/channel-socket.c | 7 +++----
> net/dgram.c | 16 +++++++++++++---
> net/l2tpv3.c | 5 +++--
> net/socket.c | 20 ++++++++++++++++----
> qga/channel-posix.c | 7 ++++++-
> tests/unit/socket-helpers.c | 5 ++++-
> tests/unit/test-crypto-tlssession.c | 8 ++++----
> util/oslib-posix.c | 7 -------
> util/oslib-win32.c | 5 -----
> util/vhost-user-server.c | 4 ++--
> 14 files changed, 63 insertions(+), 37 deletions(-)
>
> diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
> index 2f3c7320a6..a65943d0b8 100644
> --- a/contrib/ivshmem-server/ivshmem-server.c
> +++ b/contrib/ivshmem-server/ivshmem-server.c
> @@ -146,9 +146,13 @@ ivshmem_server_handle_new_conn(IvshmemServer *server)
> return -1;
> }
>
> - qemu_socket_set_nonblock(newfd);
> IVSHMEM_SERVER_DEBUG(server, "accept()=%d\n", newfd);
>
> + if (!qemu_set_blocking(newfd, false, NULL)) {
&error_warn here so we diagnose the reason we're returning -1
to the caller ?
> + close(newfd);
> + return -1;
> + }
> +
> /* allocate new structure for this peer */
> peer = g_malloc0(sizeof(*peer));
> peer->sock_fd = newfd;
> diff --git a/tests/unit/socket-helpers.c b/tests/unit/socket-helpers.c
> index 37db24f72a..1b7e283f24 100644
> --- a/tests/unit/socket-helpers.c
> +++ b/tests/unit/socket-helpers.c
> @@ -88,7 +88,10 @@ static int socket_can_bind_connect(const char *hostname, int family)
> goto cleanup;
> }
>
> - qemu_socket_set_nonblock(cfd);
> + if (!qemu_set_blocking(cfd, false, NULL)) {
&error_abort here.
> + goto cleanup;
> + }
> +
> if (connect(cfd, (struct sockaddr *)&ss, sslen) < 0) {
> if (errno == EINPROGRESS) {
> check_soerr = true;
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 :|
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 5/8] util: drop qemu_socket_try_set_nonblock()
2025-09-11 9:20 ` [PATCH v2 5/8] util: drop qemu_socket_try_set_nonblock() Vladimir Sementsov-Ogievskiy
@ 2025-09-12 17:00 ` Daniel P. Berrangé
0 siblings, 0 replies; 22+ messages in thread
From: Daniel P. Berrangé @ 2025-09-12 17:00 UTC (permalink / raw)
To: Vladimir Sementsov-Ogievskiy
Cc: qemu-devel, peterx, qemu-block, leiyang, marcandre.lureau,
Jason Wang, Paolo Bonzini, Stefan Weil
On Thu, Sep 11, 2025 at 12:20:03PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> Now we can use qemu_set_blocking() in these cases.
>
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
> Reviewed-by: Peter Xu <peterx@redhat.com>
> ---
> include/qemu/sockets.h | 1 -
> net/dgram.c | 12 +++---------
> net/socket.c | 7 ++-----
> net/stream.c | 9 +++------
> net/stream_data.c | 10 ++++------
> util/oslib-posix.c | 4 ----
> util/oslib-win32.c | 9 ---------
> 7 files changed, 12 insertions(+), 40 deletions(-)
>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
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 :|
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 6/8] io/channel-socket: rework qio_channel_socket_copy_fds()
2025-09-11 9:20 ` [PATCH v2 6/8] io/channel-socket: rework qio_channel_socket_copy_fds() Vladimir Sementsov-Ogievskiy
@ 2025-09-12 17:05 ` Daniel P. Berrangé
2025-09-15 8:47 ` Vladimir Sementsov-Ogievskiy
0 siblings, 1 reply; 22+ messages in thread
From: Daniel P. Berrangé @ 2025-09-12 17:05 UTC (permalink / raw)
To: Vladimir Sementsov-Ogievskiy
Cc: qemu-devel, peterx, qemu-block, leiyang, marcandre.lureau
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 <vsementsov@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 :|
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 7/8] util: drop qemu_socket_set_block()
2025-09-11 9:20 ` [PATCH v2 7/8] util: drop qemu_socket_set_block() Vladimir Sementsov-Ogievskiy
@ 2025-09-12 17:06 ` Daniel P. Berrangé
0 siblings, 0 replies; 22+ messages in thread
From: Daniel P. Berrangé @ 2025-09-12 17:06 UTC (permalink / raw)
To: Vladimir Sementsov-Ogievskiy
Cc: qemu-devel, peterx, qemu-block, leiyang, marcandre.lureau,
Paolo Bonzini, Stefan Weil
On Thu, Sep 11, 2025 at 12:20:05PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> Now it's unused.
>
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
> ---
> include/qemu/sockets.h | 1 -
> util/oslib-posix.c | 6 ------
> util/oslib-win32.c | 7 -------
> 3 files changed, 14 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
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 :|
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 8/8] use qemu_set_blocking instead of g_unix_set_fd_nonblocking
2025-09-11 9:20 ` [PATCH v2 8/8] use qemu_set_blocking instead of g_unix_set_fd_nonblocking Vladimir Sementsov-Ogievskiy
@ 2025-09-12 17:11 ` Daniel P. Berrangé
2025-09-15 10:04 ` Vladimir Sementsov-Ogievskiy
0 siblings, 1 reply; 22+ messages in thread
From: Daniel P. Berrangé @ 2025-09-12 17:11 UTC (permalink / raw)
To: Vladimir Sementsov-Ogievskiy
Cc: qemu-devel, peterx, qemu-block, leiyang, marcandre.lureau,
Paolo Bonzini, Michael S. Tsirkin, Gerd Hoffmann, Gustavo Romero,
Stefano Garzarella, Jason Wang, Michael Roth, Kostiantyn Kostiuk,
Alexander Bulekov, Bandan Das, Stefan Hajnoczi, Fabiano Rosas,
Darren Kenny, Qiuhao Li, Laurent Vivier
On Thu, Sep 11, 2025 at 12:20:06PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> Instead of open-coded g_unix_set_fd_nonblocking() calls, use
> QEMU wrapper qemu_set_blocking().
>
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
> ---
> chardev/char-fd.c | 4 ++--
> chardev/char-pty.c | 3 +--
> chardev/char-serial.c | 3 +--
> chardev/char-stdio.c | 3 +--
> hw/input/virtio-input-host.c | 3 +--
> hw/misc/ivshmem-flat.c | 3 ++-
> hw/misc/ivshmem-pci.c | 7 ++++++-
> hw/virtio/vhost-vsock.c | 8 ++------
> io/channel-command.c | 9 ++++++---
> io/channel-file.c | 3 +--
> net/tap-bsd.c | 12 ++++++++++--
> net/tap-linux.c | 7 ++++++-
> net/tap-solaris.c | 7 ++++++-
> net/tap.c | 21 ++++++---------------
> qga/commands-posix.c | 3 +--
> tests/qtest/fuzz/virtio_net_fuzz.c | 2 +-
> tests/qtest/vhost-user-test.c | 3 +--
> tests/unit/test-iov.c | 5 +++--
> ui/input-linux.c | 3 +--
> util/event_notifier-posix.c | 4 ++--
> util/main-loop.c | 5 ++++-
> 21 files changed, 64 insertions(+), 54 deletions(-)
>
> diff --git a/chardev/char-fd.c b/chardev/char-fd.c
> index 6f03adf872..739dc68c36 100644
> --- a/chardev/char-fd.c
> +++ b/chardev/char-fd.c
> @@ -212,8 +212,8 @@ void qemu_chr_open_fd(Chardev *chr,
> FDChardev *s = FD_CHARDEV(chr);
> g_autofree char *name = NULL;
>
> - if (fd_out >= 0 && !g_unix_set_fd_nonblocking(fd_out, true, NULL)) {
> - assert(!"Failed to set FD nonblocking");
> + if (fd_out >= 0) {
> + qemu_set_blocking(fd_out, false, &error_abort);
Every caller of this method has an 'errp' available that we
can plumb into qemu_chr_open_fd().
> }
>
> if (fd_out == fd_in && fd_in >= 0) {
> diff --git a/hw/misc/ivshmem-flat.c b/hw/misc/ivshmem-flat.c
> index fe4be6be17..89495f6a11 100644
> --- a/hw/misc/ivshmem-flat.c
> +++ b/hw/misc/ivshmem-flat.c
> @@ -154,7 +154,8 @@ static void ivshmem_flat_add_vector(IvshmemFTState *s, IvshmemPeer *peer,
> * peer.
> */
> peer->vector[peer->vector_counter].id = peer->vector_counter;
> - g_unix_set_fd_nonblocking(vector_fd, true, NULL);
> + /* WARNING: qemu_socket_set_nonblock() return code ignored */
> + qemu_set_blocking(vector_fd, false, NULL);
Perhaps &warn_report so we at least diagnose this awkward situation ?
> event_notifier_init_fd(&peer->vector[peer->vector_counter].event_notifier,
> vector_fd);
>
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 :|
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 4/8] util: drop qemu_socket_set_nonblock()
2025-09-12 16:59 ` Daniel P. Berrangé
@ 2025-09-15 8:07 ` Vladimir Sementsov-Ogievskiy
2025-09-15 8:09 ` Vladimir Sementsov-Ogievskiy
1 sibling, 0 replies; 22+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2025-09-15 8:07 UTC (permalink / raw)
To: Daniel P. Berrangé
Cc: qemu-devel, peterx, qemu-block, leiyang, marcandre.lureau,
Michael S. Tsirkin, Stefano Garzarella, Jason Wang, Michael Roth,
Kostiantyn Kostiuk, Paolo Bonzini, Stefan Weil, Coiby Xu
On 12.09.25 19:59, Daniel P. Berrangé wrote:
> On Thu, Sep 11, 2025 at 12:20:02PM +0300, Vladimir Sementsov-Ogievskiy wrote:
>> Use common qemu_set_blocking() instead.
>>
>> Note that pre-patch the behavior of Win32 and Linux realizations
>> are inconsistent: we ignore failure for Win32, and assert success
>> for Linux.
>>
>> How do we convert the callers?
>
>> 3. io/channel-socket.c: here we convert both old calls to
>> qemu_socket_set_nonblock() and qemu_socket_set_block() to
>> one new call. Pre-patch we assert success for Linux in
>> qemu_socket_set_nonblock(), and ignore all other errors here.
>> Still, all callers pass errp=NULL to qio_channel_set_blocking(),
>> so after patch we ignore all errors. Switching from assertion
>> to ignoring may be not very good, but still acceptable, keeping
>> in mind that all callers of qio_channel_set_blocking() do
>> explicitly ignore the error.
>
> This is a bit questionable. IMHO the reason why nearly all
> callers pass errp=NULL is laziness based on the assumption
> that the code actually asserts, and no one thinking to check
> the win impl which didn't asset.
>
> IOW, I think we need a prior patch that sets the 'errp'
> in all these callers, either to &error_abort, or to
> propage the error if practical.
>
>> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
>> Reviewed-by: Peter Xu <peterx@redhat.com>
>> ---
>> contrib/ivshmem-server/ivshmem-server.c | 6 +++++-
>> hw/hyperv/syndbg.c | 4 +++-
>> hw/virtio/vhost-user.c | 5 ++++-
>> include/qemu/sockets.h | 1 -
>> io/channel-socket.c | 7 +++----
>> net/dgram.c | 16 +++++++++++++---
>> net/l2tpv3.c | 5 +++--
>> net/socket.c | 20 ++++++++++++++++----
>> qga/channel-posix.c | 7 ++++++-
>> tests/unit/socket-helpers.c | 5 ++++-
>> tests/unit/test-crypto-tlssession.c | 8 ++++----
>> util/oslib-posix.c | 7 -------
>> util/oslib-win32.c | 5 -----
>> util/vhost-user-server.c | 4 ++--
>> 14 files changed, 63 insertions(+), 37 deletions(-)
>>
>> diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
>> index 2f3c7320a6..a65943d0b8 100644
>> --- a/contrib/ivshmem-server/ivshmem-server.c
>> +++ b/contrib/ivshmem-server/ivshmem-server.c
>> @@ -146,9 +146,13 @@ ivshmem_server_handle_new_conn(IvshmemServer *server)
>> return -1;
>> }
>>
>> - qemu_socket_set_nonblock(newfd);
>> IVSHMEM_SERVER_DEBUG(server, "accept()=%d\n", newfd);
>>
>> + if (!qemu_set_blocking(newfd, false, NULL)) {
>
> &error_warn here so we diagnose the reason we're returning -1
> to the caller ?
O, I missed we have error_warn already. It was always my dream to implement it, but never got around to it.
Ok
>
>> + close(newfd);
>> + return -1;
>> + }
>> +
>> /* allocate new structure for this peer */
>> peer = g_malloc0(sizeof(*peer));
>> peer->sock_fd = newfd;
>
>> diff --git a/tests/unit/socket-helpers.c b/tests/unit/socket-helpers.c
>> index 37db24f72a..1b7e283f24 100644
>> --- a/tests/unit/socket-helpers.c
>> +++ b/tests/unit/socket-helpers.c
>> @@ -88,7 +88,10 @@ static int socket_can_bind_connect(const char *hostname, int family)
>> goto cleanup;
>> }
>>
>> - qemu_socket_set_nonblock(cfd);
>> + if (!qemu_set_blocking(cfd, false, NULL)) {
>
> &error_abort here.
Ok
>
>> + goto cleanup;
>> + }
>> +
>> if (connect(cfd, (struct sockaddr *)&ss, sslen) < 0) {
>> if (errno == EINPROGRESS) {
>> check_soerr = true;
>
> With regards,
> Daniel
--
Best regards,
Vladimir
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 4/8] util: drop qemu_socket_set_nonblock()
2025-09-12 16:59 ` Daniel P. Berrangé
2025-09-15 8:07 ` Vladimir Sementsov-Ogievskiy
@ 2025-09-15 8:09 ` Vladimir Sementsov-Ogievskiy
1 sibling, 0 replies; 22+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2025-09-15 8:09 UTC (permalink / raw)
To: Daniel P. Berrangé
Cc: qemu-devel, peterx, qemu-block, leiyang, marcandre.lureau,
Michael S. Tsirkin, Stefano Garzarella, Jason Wang, Michael Roth,
Kostiantyn Kostiuk, Paolo Bonzini, Stefan Weil, Coiby Xu
On 12.09.25 19:59, Daniel P. Berrangé wrote:
> On Thu, Sep 11, 2025 at 12:20:02PM +0300, Vladimir Sementsov-Ogievskiy wrote:
>> Use common qemu_set_blocking() instead.
>>
>> Note that pre-patch the behavior of Win32 and Linux realizations
>> are inconsistent: we ignore failure for Win32, and assert success
>> for Linux.
>>
>> How do we convert the callers?
>> 3. io/channel-socket.c: here we convert both old calls to
>> qemu_socket_set_nonblock() and qemu_socket_set_block() to
>> one new call. Pre-patch we assert success for Linux in
>> qemu_socket_set_nonblock(), and ignore all other errors here.
>> Still, all callers pass errp=NULL to qio_channel_set_blocking(),
>> so after patch we ignore all errors. Switching from assertion
>> to ignoring may be not very good, but still acceptable, keeping
>> in mind that all callers of qio_channel_set_blocking() do
>> explicitly ignore the error.
> This is a bit questionable. IMHO the reason why nearly all
> callers pass errp=NULL is laziness based on the assumption
> that the code actually asserts, and no one thinking to check
> the win impl which didn't asset.
>
> IOW, I think we need a prior patch that sets the 'errp'
> in all these callers, either to &error_abort, or to
> propage the error if practical.
To be honest, I thought about it. I'll try.
--
Best regards,
Vladimir
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 6/8] io/channel-socket: rework qio_channel_socket_copy_fds()
2025-09-12 17:05 ` Daniel P. Berrangé
@ 2025-09-15 8:47 ` Vladimir Sementsov-Ogievskiy
0 siblings, 0 replies; 22+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2025-09-15 8:47 UTC (permalink / raw)
To: Daniel P. Berrangé
Cc: qemu-devel, peterx, qemu-block, leiyang, marcandre.lureau
On 12.09.25 20:05, Daniel P. Berrangé wrote:
> 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 <vsementsov@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++) {
Ok. Didn't know it's acceptable)
I missed
4b77429adbecf9 "docs/style: permit inline loop variables"
>
>> + if (*fd < 0) {
>> + continue;
>> }
>> - *nfds += gotfds;
>> + close(*fd);
>> }
>> +
>> + g_free(fds);
>
> Then here we can use:
>
> g_clear_poointer(fds, g_free);
> *nfds = 0;
>
Ok
>> }
>>
>>
>> @@ -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.
This way, we'll still modify user given fds on failure path (to NULL). But that's not a big deal, of course.
>
>> }
>>
>> return ret;
>> --
>> 2.48.1
>>
>
> With regards,
> Daniel
--
Best regards,
Vladimir
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 8/8] use qemu_set_blocking instead of g_unix_set_fd_nonblocking
2025-09-12 17:11 ` Daniel P. Berrangé
@ 2025-09-15 10:04 ` Vladimir Sementsov-Ogievskiy
0 siblings, 0 replies; 22+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2025-09-15 10:04 UTC (permalink / raw)
To: Daniel P. Berrangé
Cc: qemu-devel, peterx, qemu-block, leiyang, marcandre.lureau,
Paolo Bonzini, Michael S. Tsirkin, Gerd Hoffmann, Gustavo Romero,
Stefano Garzarella, Jason Wang, Michael Roth, Kostiantyn Kostiuk,
Alexander Bulekov, Bandan Das, Stefan Hajnoczi, Fabiano Rosas,
Darren Kenny, Qiuhao Li, Laurent Vivier
On 12.09.25 20:11, Daniel P. Berrangé wrote:
> On Thu, Sep 11, 2025 at 12:20:06PM +0300, Vladimir Sementsov-Ogievskiy wrote:
>> Instead of open-coded g_unix_set_fd_nonblocking() calls, use
>> QEMU wrapper qemu_set_blocking().
>>
>> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
>> ---
>> chardev/char-fd.c | 4 ++--
>> chardev/char-pty.c | 3 +--
>> chardev/char-serial.c | 3 +--
>> chardev/char-stdio.c | 3 +--
>> hw/input/virtio-input-host.c | 3 +--
>> hw/misc/ivshmem-flat.c | 3 ++-
>> hw/misc/ivshmem-pci.c | 7 ++++++-
>> hw/virtio/vhost-vsock.c | 8 ++------
>> io/channel-command.c | 9 ++++++---
>> io/channel-file.c | 3 +--
>> net/tap-bsd.c | 12 ++++++++++--
>> net/tap-linux.c | 7 ++++++-
>> net/tap-solaris.c | 7 ++++++-
>> net/tap.c | 21 ++++++---------------
>> qga/commands-posix.c | 3 +--
>> tests/qtest/fuzz/virtio_net_fuzz.c | 2 +-
>> tests/qtest/vhost-user-test.c | 3 +--
>> tests/unit/test-iov.c | 5 +++--
>> ui/input-linux.c | 3 +--
>> util/event_notifier-posix.c | 4 ++--
>> util/main-loop.c | 5 ++++-
>> 21 files changed, 64 insertions(+), 54 deletions(-)
>>
>> diff --git a/chardev/char-fd.c b/chardev/char-fd.c
>> index 6f03adf872..739dc68c36 100644
>> --- a/chardev/char-fd.c
>> +++ b/chardev/char-fd.c
>> @@ -212,8 +212,8 @@ void qemu_chr_open_fd(Chardev *chr,
>> FDChardev *s = FD_CHARDEV(chr);
>> g_autofree char *name = NULL;
>>
>> - if (fd_out >= 0 && !g_unix_set_fd_nonblocking(fd_out, true, NULL)) {
>> - assert(!"Failed to set FD nonblocking");
>> + if (fd_out >= 0) {
>> + qemu_set_blocking(fd_out, false, &error_abort);
>
> Every caller of this method has an 'errp' available that we
> can plumb into qemu_chr_open_fd().
Will look a it.
>
>> }
>>
>> if (fd_out == fd_in && fd_in >= 0) {
>
>
>> diff --git a/hw/misc/ivshmem-flat.c b/hw/misc/ivshmem-flat.c
>> index fe4be6be17..89495f6a11 100644
>> --- a/hw/misc/ivshmem-flat.c
>> +++ b/hw/misc/ivshmem-flat.c
>> @@ -154,7 +154,8 @@ static void ivshmem_flat_add_vector(IvshmemFTState *s, IvshmemPeer *peer,
>> * peer.
>> */
>> peer->vector[peer->vector_counter].id = peer->vector_counter;
>> - g_unix_set_fd_nonblocking(vector_fd, true, NULL);
>> + /* WARNING: qemu_socket_set_nonblock() return code ignored */
>> + qemu_set_blocking(vector_fd, false, NULL);
>
> Perhaps &warn_report so we at least diagnose this awkward situation ?
>
Ok
>> event_notifier_init_fd(&peer->vector[peer->vector_counter].event_notifier,
>> vector_fd);
>>
>
>
Thanks for reviewing!
--
Best regards,
Vladimir
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2025-09-15 10:06 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-11 9:19 [PATCH v2 0/8] io: deal with blocking/non-blocking fds Vladimir Sementsov-Ogievskiy
2025-09-11 9:19 ` [PATCH v2 1/8] char-socket: tcp_chr_recv(): drop extra _set_(block, cloexec) Vladimir Sementsov-Ogievskiy
2025-09-12 16:49 ` [PATCH v2 1/8] char-socket: tcp_chr_recv(): drop extra _set_(block,cloexec) Daniel P. Berrangé
2025-09-11 9:20 ` [PATCH v2 2/8] char-socket: tcp_chr_recv(): add comment Vladimir Sementsov-Ogievskiy
2025-09-12 16:50 ` Daniel P. Berrangé
2025-09-11 9:20 ` [PATCH v2 3/8] util: add qemu_set_blocking() function Vladimir Sementsov-Ogievskiy
2025-09-12 16:51 ` Daniel P. Berrangé
2025-09-11 9:20 ` [PATCH v2 4/8] util: drop qemu_socket_set_nonblock() Vladimir Sementsov-Ogievskiy
2025-09-12 16:59 ` Daniel P. Berrangé
2025-09-15 8:07 ` Vladimir Sementsov-Ogievskiy
2025-09-15 8:09 ` Vladimir Sementsov-Ogievskiy
2025-09-11 9:20 ` [PATCH v2 5/8] util: drop qemu_socket_try_set_nonblock() Vladimir Sementsov-Ogievskiy
2025-09-12 17:00 ` Daniel P. Berrangé
2025-09-11 9:20 ` [PATCH v2 6/8] io/channel-socket: rework qio_channel_socket_copy_fds() Vladimir Sementsov-Ogievskiy
2025-09-12 17:05 ` Daniel P. Berrangé
2025-09-15 8:47 ` Vladimir Sementsov-Ogievskiy
2025-09-11 9:20 ` [PATCH v2 7/8] util: drop qemu_socket_set_block() Vladimir Sementsov-Ogievskiy
2025-09-12 17:06 ` Daniel P. Berrangé
2025-09-11 9:20 ` [PATCH v2 8/8] use qemu_set_blocking instead of g_unix_set_fd_nonblocking Vladimir Sementsov-Ogievskiy
2025-09-12 17:11 ` Daniel P. Berrangé
2025-09-15 10:04 ` Vladimir Sementsov-Ogievskiy
2025-09-11 9:22 ` [PATCH v2 0/8] io: deal with blocking/non-blocking fds Vladimir Sementsov-Ogievskiy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).