qemu_set_blocking() relies on g_unix_set_fd_nonblocking(), which always
issues fcntl(F_SETFL) even if O_NONBLOCK already has the requested
value.  macOS rejects F_SETFL on POSIX shared memory descriptors.  The
socket channel treats this like a read error and disconnects.  Those
descriptors are passed in blocking mode anyway, so there is nothing to
change on them.  Query the flags with F_GETFL first and only issue
F_SETFL when O_NONBLOCK is actually set.

Signed-off-by: Tim Pambor <[email protected]>
---
 util/oslib-posix.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index dc001da66d..3d5bb16ca6 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -252,17 +252,29 @@ void qemu_anon_ram_free(void *ptr, size_t size)
 
 bool qemu_set_blocking(int fd, bool block, Error **errp)
 {
-    g_autoptr(GError) err = NULL;
+    int flags, new_flags;
 
-    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;
+    flags = fcntl(fd, F_GETFL);
+    if (flags < 0) {
+        goto fail;
+    }
+
+    if (block) {
+        new_flags = flags & ~O_NONBLOCK;
+    } else {
+        new_flags = flags | O_NONBLOCK;
+    }
+
+    if (new_flags != flags && fcntl(fd, F_SETFL, new_flags) < 0) {
+        goto fail;
     }
 
     return true;
+
+fail:
+    error_setg_errno(errp, errno, "Can't set file descriptor %d %s", fd,
+                     block ? "blocking" : "non-blocking");
+    return false;
 }
 
 int socket_set_fast_reuse(int fd)

-- 
2.55.0


Reply via email to