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 <vsement...@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