All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05
@ 2017-09-05  9:22 Daniel P. Berrange
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 1/9] io: fix temp directory used by test-io-channel-tls test Daniel P. Berrange
                   ` (9 more replies)
  0 siblings, 10 replies; 13+ messages in thread
From: Daniel P. Berrange @ 2017-09-05  9:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Daniel P. Berrange

The following changes since commit 32f0f68bb77289b75a82925f712bb52e16eac3ba:

  Merge remote-tracking branch 'remotes/ehabkost/tags/x86-and-machine-pull-request' into staging (2017-09-01 17:28:54 +0100)

are available in the git repository at:

  git://github.com/berrange/qemu tags/pull-qio-20170905-1

for you to fetch changes up to 33fb97121573985b4a57306b8abdb9dd992061fa:

  io: fix check for handshake completion in TLS test (2017-09-05 10:20:28 +0100)

----------------------------------------------------------------
Merge QEMU I/O 2017/09/05 v1

----------------------------------------------------------------

Cao jin (1):
  util: remove the obsolete non-blocking connect

Daniel P. Berrange (4):
  io: fix temp directory used by test-io-channel-tls test
  io: fix typo in docs comment for qio_channel_read
  io: add new qio_channel_{readv, writev, read, write}_all functions
  io: fix check for handshake completion in TLS test

Knut Omang (4):
  tests: Add test-listen - a stress test for QEMU socket listen
  sockets: factor out a new try_bind() function
  sockets: factor out create_fast_reuse_socket
  sockets: Handle race condition between binds to the same port

 block/sheepdog.c            |   2 +-
 block/ssh.c                 |   2 +-
 include/io/channel.h        |  92 +++++++++++-
 include/qemu/sockets.h      |  12 +-
 io/channel-socket.c         |   2 +-
 io/channel.c                |  94 ++++++++++++
 tests/Makefile.include      |   2 +
 tests/io-channel-helpers.c  | 102 ++-----------
 tests/test-io-channel-tls.c |   6 +-
 tests/test-listen.c         | 253 ++++++++++++++++++++++++++++++++
 util/qemu-sockets.c         | 343 +++++++++++++++-----------------------------
 11 files changed, 570 insertions(+), 340 deletions(-)
 create mode 100644 tests/test-listen.c

-- 
2.13.5

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PULL v1 1/9] io: fix temp directory used by test-io-channel-tls test
  2017-09-05  9:22 [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Daniel P. Berrange
@ 2017-09-05  9:22 ` Daniel P. Berrange
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 2/9] tests: Add test-listen - a stress test for QEMU socket listen Daniel P. Berrange
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Daniel P. Berrange @ 2017-09-05  9:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Daniel P. Berrange

The test-io-channel-tls test was mistakenly using two of the
same directories as test-crypto-tlssession. This causes a
sporadic failure when using make -j$BIGNUM.

Reported-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 tests/test-io-channel-tls.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/test-io-channel-tls.c b/tests/test-io-channel-tls.c
index 8eaa208e1b..ff96877323 100644
--- a/tests/test-io-channel-tls.c
+++ b/tests/test-io-channel-tls.c
@@ -127,8 +127,8 @@ static void test_io_channel_tls(const void *opaque)
     /* We'll use this for our fake client-server connection */
     g_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, channel) == 0);
 
-#define CLIENT_CERT_DIR "tests/test-crypto-tlssession-client/"
-#define SERVER_CERT_DIR "tests/test-crypto-tlssession-server/"
+#define CLIENT_CERT_DIR "tests/test-io-channel-tls-client/"
+#define SERVER_CERT_DIR "tests/test-io-channel-tls-server/"
     mkdir(CLIENT_CERT_DIR, 0700);
     mkdir(SERVER_CERT_DIR, 0700);
 
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PULL v1 2/9] tests: Add test-listen - a stress test for QEMU socket listen
  2017-09-05  9:22 [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Daniel P. Berrange
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 1/9] io: fix temp directory used by test-io-channel-tls test Daniel P. Berrange
@ 2017-09-05  9:22 ` Daniel P. Berrange
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 3/9] sockets: factor out a new try_bind() function Daniel P. Berrange
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Daniel P. Berrange @ 2017-09-05  9:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Knut Omang, Daniel P . Berrange

From: Knut Omang <knut.omang@oracle.com>

There's a potential race condition between multiple bind()'s
attempting to bind to the same port, which occasionally
allows more than one bind to succeed against the same port.

When a subsequent listen() call is made with the same socket
only one will succeed.

The current QEMU code does however not take this situation into account
and the listen will cause the code to break out and fail even
when there are actually available ports to use.

This test exposes two subtests:

/socket/listen-serial
/socket/listen-compete

The "compete" subtest creates a number of threads and have them all trying to bind
to the same port with a large enough offset input to
allow all threads to get it's own port.
The "serial" subtest just does the same, except in series in a
single thread.

The serial version passes, probably in most versions of QEMU.

The parallel version exposes the problem in a relatively reliable way,
eg. it fails a majority of times, but not with a 100% rate, occasional
passes can be seen. Nevertheless this is quite good given that
the bug was tricky to reproduce and has been left undetected for
a while.

The problem seems to be present in all versions of QEMU.

The original failure scenario occurred with VNC port allocation
in a traditional Xen based build, in different code
but with similar functionality.

Reported-by: Bhavesh Davda <bhavesh.davda@oracle.com>
Signed-off-by: Knut Omang <knut.omang@oracle.com>
Reviewed-by: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Bhavesh Davda <bhavesh.davda@oracle.com>
Reviewed-by: Girish Moodalbail <girish.moodalbail@oracle.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 tests/Makefile.include |   2 +
 tests/test-listen.c    | 253 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 255 insertions(+)
 create mode 100644 tests/test-listen.c

diff --git a/tests/Makefile.include b/tests/Makefile.include
index f08b7418f0..a231754517 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -151,6 +151,7 @@ check-unit-y += tests/test-bufferiszero$(EXESUF)
 gcov-files-check-bufferiszero-y = util/bufferiszero.c
 check-unit-y += tests/test-uuid$(EXESUF)
 check-unit-y += tests/ptimer-test$(EXESUF)
+#check-unit-y += tests/test-listen$(EXESUF)
 gcov-files-ptimer-test-y = hw/core/ptimer.c
 check-unit-y += tests/test-qapi-util$(EXESUF)
 gcov-files-test-qapi-util-y = qapi/qapi-util.c
@@ -796,6 +797,7 @@ tests/test-arm-mptimer$(EXESUF): tests/test-arm-mptimer.o
 tests/test-qapi-util$(EXESUF): tests/test-qapi-util.o $(test-util-obj-y)
 tests/numa-test$(EXESUF): tests/numa-test.o
 tests/vmgenid-test$(EXESUF): tests/vmgenid-test.o tests/boot-sector.o tests/acpi-utils.o
+tests/test-listen$(EXESUF): tests/test-listen.o $(test-util-obj-y)
 
 tests/migration/stress$(EXESUF): tests/migration/stress.o
 	$(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"LINK","$(TARGET_DIR)$@")
diff --git a/tests/test-listen.c b/tests/test-listen.c
new file mode 100644
index 0000000000..03c4c8f03b
--- /dev/null
+++ b/tests/test-listen.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Knut Omang <knut.omang@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or later
+ * as published by the Free Software Foundation.
+ *
+ * Test parallel port listen configuration with
+ * dynamic port allocation
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "qemu-common.h"
+#include "qemu/thread.h"
+#include "qemu/sockets.h"
+#include "qapi/error.h"
+
+#define NAME_LEN 1024
+#define PORT_LEN 16
+
+struct thr_info {
+    QemuThread thread;
+    int to_port;
+    bool ipv4;
+    bool ipv6;
+    int got_port;
+    int eno;
+    int fd;
+    const char *errstr;
+    char hostname[NAME_LEN + 1];
+    char port[PORT_LEN + 1];
+};
+
+
+/* These two functions taken from test-io-channel-socket.c */
+static int check_bind(const char *hostname, bool *has_proto)
+{
+    int fd = -1;
+    struct addrinfo ai, *res = NULL;
+    int rc;
+    int ret = -1;
+
+    memset(&ai, 0, sizeof(ai));
+    ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
+    ai.ai_family = AF_UNSPEC;
+    ai.ai_socktype = SOCK_STREAM;
+
+    /* lookup */
+    rc = getaddrinfo(hostname, NULL, &ai, &res);
+    if (rc != 0) {
+        if (rc == EAI_ADDRFAMILY ||
+            rc == EAI_FAMILY) {
+            *has_proto = false;
+            goto done;
+        }
+        goto cleanup;
+    }
+
+    fd = qemu_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+    if (fd < 0) {
+        goto cleanup;
+    }
+
+    if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) {
+        if (errno == EADDRNOTAVAIL) {
+            *has_proto = false;
+            goto done;
+        }
+        goto cleanup;
+    }
+
+    *has_proto = true;
+ done:
+    ret = 0;
+
+ cleanup:
+    if (fd != -1) {
+        close(fd);
+    }
+    if (res) {
+        freeaddrinfo(res);
+    }
+    return ret;
+}
+
+static int check_protocol_support(bool *has_ipv4, bool *has_ipv6)
+{
+    if (check_bind("127.0.0.1", has_ipv4) < 0) {
+        return -1;
+    }
+    if (check_bind("::1", has_ipv6) < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static void *listener_thread(void *arg)
+{
+    struct thr_info *thr = (struct thr_info *)arg;
+    SocketAddress addr = {
+        .type = SOCKET_ADDRESS_TYPE_INET,
+        .u = {
+            .inet = {
+                .host = thr->hostname,
+                .port = thr->port,
+                .has_ipv4 = thr->ipv4,
+                .ipv4 = thr->ipv4,
+                .has_ipv6 = thr->ipv6,
+                .ipv6 = thr->ipv6,
+                .has_to = true,
+                .to = thr->to_port,
+            },
+        },
+    };
+    Error *err = NULL;
+    int fd;
+
+    fd = socket_listen(&addr, &err);
+    if (fd < 0) {
+        thr->eno = errno;
+        thr->errstr = error_get_pretty(err);
+    } else {
+        struct sockaddr_in a;
+        socklen_t a_len = sizeof(a);
+        g_assert_cmpint(getsockname(fd, (struct sockaddr *)&a, &a_len), ==, 0);
+        thr->got_port = ntohs(a.sin_port);
+        thr->fd = fd;
+    }
+    return arg;
+}
+
+
+static void listen_compete_nthr(bool threaded, int nthreads,
+                                int start_port, int max_offset,
+                                bool ipv4, bool ipv6)
+{
+    int i;
+    int failed_listens = 0;
+    struct thr_info *thr = g_new0(struct thr_info, nthreads);
+    int used[max_offset + 1];
+
+    memset(used, 0, sizeof(used));
+    for (i = 0; i < nthreads; i++) {
+        snprintf(thr[i].port, PORT_LEN, "%d", start_port);
+        strcpy(thr[i].hostname, "localhost");
+        thr[i].to_port = start_port + max_offset;
+        thr[i].ipv4 = ipv4;
+        thr[i].ipv6 = ipv6;
+    }
+
+    for (i = 0; i < nthreads; i++) {
+        if (threaded) {
+            qemu_thread_create(&thr[i].thread, "listener",
+                               listener_thread, &thr[i],
+                               QEMU_THREAD_JOINABLE);
+        } else {
+            listener_thread(&thr[i]);
+        }
+    }
+
+    if (threaded) {
+        for (i = 0; i < nthreads; i++) {
+            qemu_thread_join(&thr[i].thread);
+        }
+    }
+    for (i = 0; i < nthreads; i++) {
+        if (thr[i].got_port) {
+            closesocket(thr[i].fd);
+        }
+    }
+
+    for (i = 0; i < nthreads; i++) {
+        if (thr[i].eno != 0) {
+            const char *m;
+            g_printerr("** Failed to assign a port to thread %d (errno = %d)\n",
+                   i, thr[i].eno);
+            /* This is what we are interested in capturing -
+             * catch and report details if something unexpected happens:
+             */
+            m = strstr(thr[i].errstr, "Failed to listen on socket");
+            if (m != NULL) {
+                g_assert_cmpstr(thr[i].errstr, ==,
+                    "Failed to listen on socket: Address already in use");
+            }
+            failed_listens++;
+        } else {
+            int assigned_port = thr[i].got_port;
+            g_assert_cmpint(assigned_port, <= , thr[i].to_port);
+            g_assert_cmpint(used[assigned_port - start_port], == , 0);
+        }
+    }
+    g_assert_cmpint(failed_listens, ==, 0);
+    g_free(thr);
+}
+
+
+static void listen_compete_ipv4(void)
+{
+    listen_compete_nthr(true, 200, 5920, 300, true, false);
+}
+
+static void listen_serial_ipv4(void)
+{
+    listen_compete_nthr(false, 200, 6300, 300, true, false);
+}
+
+static void listen_compete_ipv6(void)
+{
+    listen_compete_nthr(true, 200, 5920, 300, true, false);
+}
+
+static void listen_serial_ipv6(void)
+{
+    listen_compete_nthr(false, 200, 6300, 300, false, true);
+}
+
+static void listen_compete_gen(void)
+{
+    listen_compete_nthr(true, 200, 5920, 300, true, true);
+}
+
+static void listen_serial_gen(void)
+{
+    listen_compete_nthr(false, 200, 6300, 300, true, true);
+}
+
+
+int main(int argc, char **argv)
+{
+    bool has_ipv4, has_ipv6;
+    g_test_init(&argc, &argv, NULL);
+
+    if (check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
+        return 1;
+    }
+
+    if (has_ipv4) {
+        g_test_add_func("/socket/listen-serial/ipv4", listen_serial_ipv4);
+        g_test_add_func("/socket/listen-compete/ipv4", listen_compete_ipv4);
+    }
+    if (has_ipv6) {
+        g_test_add_func("/socket/listen-serial/ipv6", listen_serial_ipv6);
+        g_test_add_func("/socket/listen-compete/ipv6", listen_compete_ipv6);
+    }
+    if (has_ipv4 && has_ipv6) {
+        g_test_add_func("/socket/listen-serial/generic", listen_serial_gen);
+        g_test_add_func("/socket/listen-compete/generic", listen_compete_gen);
+    }
+    return g_test_run();
+}
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PULL v1 3/9] sockets: factor out a new try_bind() function
  2017-09-05  9:22 [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Daniel P. Berrange
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 1/9] io: fix temp directory used by test-io-channel-tls test Daniel P. Berrange
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 2/9] tests: Add test-listen - a stress test for QEMU socket listen Daniel P. Berrange
@ 2017-09-05  9:22 ` Daniel P. Berrange
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 4/9] sockets: factor out create_fast_reuse_socket Daniel P. Berrange
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Daniel P. Berrange @ 2017-09-05  9:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Knut Omang, Daniel P . Berrange

From: Knut Omang <knut.omang@oracle.com>

A refactoring step to prepare for the problem
exposed by the test-listen test in the previous commit.

Simplify and reorganize the IPv6 specific extra
measures and move it out of the for loop to increase
code readability. No semantic changes.

Signed-off-by: Knut Omang <knut.omang@oracle.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 util/qemu-sockets.c | 69 ++++++++++++++++++++++++++++++-----------------------
 1 file changed, 39 insertions(+), 30 deletions(-)

diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 1358c81bcc..b4a2f243f4 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -149,6 +149,44 @@ int inet_ai_family_from_address(InetSocketAddress *addr,
     return PF_UNSPEC;
 }
 
+static int try_bind(int socket, InetSocketAddress *saddr, struct addrinfo *e)
+{
+#ifndef IPV6_V6ONLY
+    return bind(socket, e->ai_addr, e->ai_addrlen);
+#else
+    /*
+     * Deals with first & last cases in matrix in comment
+     * for inet_ai_family_from_address().
+     */
+    int v6only =
+        ((!saddr->has_ipv4 && !saddr->has_ipv6) ||
+         (saddr->has_ipv4 && saddr->ipv4 &&
+          saddr->has_ipv6 && saddr->ipv6)) ? 0 : 1;
+    int stat;
+
+ rebind:
+    if (e->ai_family == PF_INET6) {
+        qemu_setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, &v6only,
+                        sizeof(v6only));
+    }
+
+    stat = bind(socket, e->ai_addr, e->ai_addrlen);
+    if (!stat) {
+        return 0;
+    }
+
+    /* If we got EADDRINUSE from an IPv6 bind & v6only is unset,
+     * it could be that the IPv4 port is already claimed, so retry
+     * with v6only set
+     */
+    if (e->ai_family == PF_INET6 && errno == EADDRINUSE && !v6only) {
+        v6only = 1;
+        goto rebind;
+    }
+    return stat;
+#endif
+}
+
 static int inet_listen_saddr(InetSocketAddress *saddr,
                              int port_offset,
                              bool update_addr,
@@ -228,39 +266,10 @@ static int inet_listen_saddr(InetSocketAddress *saddr,
         port_min = inet_getport(e);
         port_max = saddr->has_to ? saddr->to + port_offset : port_min;
         for (p = port_min; p <= port_max; p++) {
-#ifdef IPV6_V6ONLY
-            /*
-             * Deals with first & last cases in matrix in comment
-             * for inet_ai_family_from_address().
-             */
-            int v6only =
-                ((!saddr->has_ipv4 && !saddr->has_ipv6) ||
-                 (saddr->has_ipv4 && saddr->ipv4 &&
-                  saddr->has_ipv6 && saddr->ipv6)) ? 0 : 1;
-#endif
             inet_setport(e, p);
-#ifdef IPV6_V6ONLY
-        rebind:
-            if (e->ai_family == PF_INET6) {
-                qemu_setsockopt(slisten, IPPROTO_IPV6, IPV6_V6ONLY, &v6only,
-                                sizeof(v6only));
-            }
-#endif
-            if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
+            if (try_bind(slisten, saddr, e) >= 0) {
                 goto listen;
             }
-
-#ifdef IPV6_V6ONLY
-            /* If we got EADDRINUSE from an IPv6 bind & V6ONLY is unset,
-             * it could be that the IPv4 port is already claimed, so retry
-             * with V6ONLY set
-             */
-            if (e->ai_family == PF_INET6 && errno == EADDRINUSE && !v6only) {
-                v6only = 1;
-                goto rebind;
-            }
-#endif
-
             if (p == port_max) {
                 if (!e->ai_next) {
                     error_setg_errno(errp, errno, "Failed to bind socket");
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PULL v1 4/9] sockets: factor out create_fast_reuse_socket
  2017-09-05  9:22 [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Daniel P. Berrange
                   ` (2 preceding siblings ...)
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 3/9] sockets: factor out a new try_bind() function Daniel P. Berrange
@ 2017-09-05  9:22 ` Daniel P. Berrange
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 5/9] sockets: Handle race condition between binds to the same port Daniel P. Berrange
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Daniel P. Berrange @ 2017-09-05  9:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Knut Omang, Daniel P . Berrange

From: Knut Omang <knut.omang@oracle.com>

Another refactoring step to prepare for fixing the problem
exposed with the test-listen test in the previous commit

Signed-off-by: Knut Omang <knut.omang@oracle.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 util/qemu-sockets.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index b4a2f243f4..d0d20476e5 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -149,6 +149,16 @@ int inet_ai_family_from_address(InetSocketAddress *addr,
     return PF_UNSPEC;
 }
 
+static int create_fast_reuse_socket(struct addrinfo *e)
+{
+    int slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
+    if (slisten < 0) {
+        return -1;
+    }
+    socket_set_fast_reuse(slisten);
+    return slisten;
+}
+
 static int try_bind(int socket, InetSocketAddress *saddr, struct addrinfo *e)
 {
 #ifndef IPV6_V6ONLY
@@ -253,7 +263,8 @@ static int inet_listen_saddr(InetSocketAddress *saddr,
         getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
 		        uaddr,INET6_ADDRSTRLEN,uport,32,
 		        NI_NUMERICHOST | NI_NUMERICSERV);
-        slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
+
+        slisten = create_fast_reuse_socket(e);
         if (slisten < 0) {
             if (!e->ai_next) {
                 error_setg_errno(errp, errno, "Failed to create socket");
@@ -261,8 +272,6 @@ static int inet_listen_saddr(InetSocketAddress *saddr,
             continue;
         }
 
-        socket_set_fast_reuse(slisten);
-
         port_min = inet_getport(e);
         port_max = saddr->has_to ? saddr->to + port_offset : port_min;
         for (p = port_min; p <= port_max; p++) {
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PULL v1 5/9] sockets: Handle race condition between binds to the same port
  2017-09-05  9:22 [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Daniel P. Berrange
                   ` (3 preceding siblings ...)
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 4/9] sockets: factor out create_fast_reuse_socket Daniel P. Berrange
@ 2017-09-05  9:22 ` Daniel P. Berrange
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 6/9] util: remove the obsolete non-blocking connect Daniel P. Berrange
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Daniel P. Berrange @ 2017-09-05  9:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Knut Omang, Daniel P . Berrange

From: Knut Omang <knut.omang@oracle.com>

If an offset of ports is specified to the inet_listen_saddr function(),
and two or more processes tries to bind from these ports at the same time,
occasionally more than one process may be able to bind to the same
port. The condition is detected by listen() but too late to avoid a failure.

This function is called by socket_listen() and used
by all socket listening code in QEMU, so all cases where any form of dynamic
port selection is used should be subject to this issue.

Add code to close and re-establish the socket when this
condition is observed, hiding the race condition from the user.

Also clean up some issues with error handling to allow more
accurate reporting of the cause of an error.

This has been developed and tested by means of the
test-listen unit test in the previous commit.
Enable the test for make check now that it passes.

Reviewed-by: Bhavesh Davda <bhavesh.davda@oracle.com>
Reviewed-by: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Girish Moodalbail <girish.moodalbail@oracle.com>
Signed-off-by: Knut Omang <knut.omang@oracle.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 tests/Makefile.include |  2 +-
 util/qemu-sockets.c    | 58 +++++++++++++++++++++++++++++++++++---------------
 2 files changed, 42 insertions(+), 18 deletions(-)

diff --git a/tests/Makefile.include b/tests/Makefile.include
index a231754517..eef4088d5c 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -151,7 +151,7 @@ check-unit-y += tests/test-bufferiszero$(EXESUF)
 gcov-files-check-bufferiszero-y = util/bufferiszero.c
 check-unit-y += tests/test-uuid$(EXESUF)
 check-unit-y += tests/ptimer-test$(EXESUF)
-#check-unit-y += tests/test-listen$(EXESUF)
+check-unit-y += tests/test-listen$(EXESUF)
 gcov-files-ptimer-test-y = hw/core/ptimer.c
 check-unit-y += tests/test-qapi-util$(EXESUF)
 gcov-files-test-qapi-util-y = qapi/qapi-util.c
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index d0d20476e5..6a511fbf76 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -206,7 +206,10 @@ static int inet_listen_saddr(InetSocketAddress *saddr,
     char port[33];
     char uaddr[INET6_ADDRSTRLEN+1];
     char uport[33];
-    int slisten, rc, port_min, port_max, p;
+    int rc, port_min, port_max, p;
+    int slisten = 0;
+    int saved_errno = 0;
+    bool socket_created = false;
     Error *err = NULL;
 
     memset(&ai,0, sizeof(ai));
@@ -258,7 +261,7 @@ static int inet_listen_saddr(InetSocketAddress *saddr,
         return -1;
     }
 
-    /* create socket + bind */
+    /* create socket + bind/listen */
     for (e = res; e != NULL; e = e->ai_next) {
         getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
 		        uaddr,INET6_ADDRSTRLEN,uport,32,
@@ -266,37 +269,58 @@ static int inet_listen_saddr(InetSocketAddress *saddr,
 
         slisten = create_fast_reuse_socket(e);
         if (slisten < 0) {
-            if (!e->ai_next) {
-                error_setg_errno(errp, errno, "Failed to create socket");
-            }
             continue;
         }
 
+        socket_created = true;
         port_min = inet_getport(e);
         port_max = saddr->has_to ? saddr->to + port_offset : port_min;
         for (p = port_min; p <= port_max; p++) {
             inet_setport(e, p);
-            if (try_bind(slisten, saddr, e) >= 0) {
-                goto listen;
-            }
-            if (p == port_max) {
-                if (!e->ai_next) {
+            rc = try_bind(slisten, saddr, e);
+            if (rc) {
+                if (errno == EADDRINUSE) {
+                    continue;
+                } else {
                     error_setg_errno(errp, errno, "Failed to bind socket");
+                    goto listen_failed;
                 }
             }
+            if (!listen(slisten, 1)) {
+                goto listen_ok;
+            }
+            if (errno != EADDRINUSE) {
+                error_setg_errno(errp, errno, "Failed to listen on socket");
+                goto listen_failed;
+            }
+            /* Someone else managed to bind to the same port and beat us
+             * to listen on it! Socket semantics does not allow us to
+             * recover from this situation, so we need to recreate the
+             * socket to allow bind attempts for subsequent ports:
+             */
+            closesocket(slisten);
+            slisten = create_fast_reuse_socket(e);
+            if (slisten < 0) {
+                error_setg_errno(errp, errno,
+                                 "Failed to recreate failed listening socket");
+                goto listen_failed;
+            }
         }
+    }
+    error_setg_errno(errp, errno,
+                     socket_created ?
+                     "Failed to find an available port" :
+                     "Failed to create a socket");
+listen_failed:
+    saved_errno = errno;
+    if (slisten >= 0) {
         closesocket(slisten);
     }
     freeaddrinfo(res);
+    errno = saved_errno;
     return -1;
 
-listen:
-    if (listen(slisten,1) != 0) {
-        error_setg_errno(errp, errno, "Failed to listen on socket");
-        closesocket(slisten);
-        freeaddrinfo(res);
-        return -1;
-    }
+listen_ok:
     if (update_addr) {
         g_free(saddr->host);
         saddr->host = g_strdup(uaddr);
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PULL v1 6/9] util: remove the obsolete non-blocking connect
  2017-09-05  9:22 [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Daniel P. Berrange
                   ` (4 preceding siblings ...)
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 5/9] sockets: Handle race condition between binds to the same port Daniel P. Berrange
@ 2017-09-05  9:22 ` Daniel P. Berrange
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 7/9] io: fix typo in docs comment for qio_channel_read Daniel P. Berrange
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Daniel P. Berrange @ 2017-09-05  9:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Cao jin, Mao Zhongyi, Daniel P . Berrange

From: Cao jin <caoj.fnst@cn.fujitsu.com>

The non-blocking connect mechanism is obsolete, and it doesn't
work well in inet connection, because it will call getaddrinfo
first and getaddrinfo will blocks on DNS lookups. Since commit
e65c67e4 & d984464e, the non-blocking connect of migration goes
through QIOChannel in a different manner(using a thread), and
nobody use this old non-blocking connect anymore.

Any newly written code which needs a non-blocking connect should
use the QIOChannel code, so we can drop NonBlockingConnectHandler
as a concept entirely.

Suggested-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Cao jin <caoj.fnst@cn.fujitsu.com>
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 block/sheepdog.c       |   2 +-
 block/ssh.c            |   2 +-
 include/qemu/sockets.h |  12 +--
 io/channel-socket.c    |   2 +-
 util/qemu-sockets.c    | 205 ++++++-------------------------------------------
 5 files changed, 28 insertions(+), 195 deletions(-)

diff --git a/block/sheepdog.c b/block/sheepdog.c
index abb2e79065..64ab07f3b7 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -591,7 +591,7 @@ static int connect_to_sdog(BDRVSheepdogState *s, Error **errp)
 {
     int fd;
 
-    fd = socket_connect(s->addr, NULL, NULL, errp);
+    fd = socket_connect(s->addr, errp);
 
     if (s->addr->type == SOCKET_ADDRESS_TYPE_INET && fd >= 0) {
         int ret = socket_set_nodelay(fd);
diff --git a/block/ssh.c b/block/ssh.c
index e8f0404c03..b049a16eb9 100644
--- a/block/ssh.c
+++ b/block/ssh.c
@@ -678,7 +678,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
     }
 
     /* Open the socket and connect. */
-    s->sock = inet_connect_saddr(s->inet, NULL, NULL, errp);
+    s->sock = inet_connect_saddr(s->inet, errp);
     if (s->sock < 0) {
         ret = -EIO;
         goto err;
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index ef6b5591f7..639cc079d9 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -27,18 +27,11 @@ int socket_set_fast_reuse(int fd);
 #define SHUT_RDWR 2
 #endif
 
-/* callback function for nonblocking connect
- * valid fd on success, negative error code on failure
- */
-typedef void NonBlockingConnectHandler(int fd, Error *err, void *opaque);
-
 int inet_ai_family_from_address(InetSocketAddress *addr,
                                 Error **errp);
 int inet_parse(InetSocketAddress *addr, const char *str, Error **errp);
 int inet_connect(const char *str, Error **errp);
-int inet_connect_saddr(InetSocketAddress *saddr,
-                       NonBlockingConnectHandler *callback, void *opaque,
-                       Error **errp);
+int inet_connect_saddr(InetSocketAddress *saddr, Error **errp);
 
 NetworkAddressFamily inet_netfamily(int family);
 
@@ -46,8 +39,7 @@ int unix_listen(const char *path, char *ostr, int olen, Error **errp);
 int unix_connect(const char *path, Error **errp);
 
 SocketAddress *socket_parse(const char *str, Error **errp);
-int socket_connect(SocketAddress *addr, NonBlockingConnectHandler *callback,
-                   void *opaque, Error **errp);
+int socket_connect(SocketAddress *addr, Error **errp);
 int socket_listen(SocketAddress *addr, Error **errp);
 void socket_listen_cleanup(int fd, Error **errp);
 int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
diff --git a/io/channel-socket.c b/io/channel-socket.c
index 591d27e8c3..563e297357 100644
--- a/io/channel-socket.c
+++ b/io/channel-socket.c
@@ -140,7 +140,7 @@ int qio_channel_socket_connect_sync(QIOChannelSocket *ioc,
     int fd;
 
     trace_qio_channel_socket_connect_sync(ioc, addr);
-    fd = socket_connect(addr, NULL, NULL, errp);
+    fd = socket_connect(addr, errp);
     if (fd < 0) {
         trace_qio_channel_socket_connect_fail(ioc);
         return -1;
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 6a511fbf76..b47fb45885 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -342,88 +342,19 @@ listen_ok:
     ((rc) == -EINPROGRESS)
 #endif
 
-/* Struct to store connect state for non blocking connect */
-typedef struct ConnectState {
-    int fd;
-    struct addrinfo *addr_list;
-    struct addrinfo *current_addr;
-    NonBlockingConnectHandler *callback;
-    void *opaque;
-} ConnectState;
-
-static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
-                             ConnectState *connect_state, Error **errp);
+static int inet_connect_addr(struct addrinfo *addr, Error **errp);
 
-static void wait_for_connect(void *opaque)
-{
-    ConnectState *s = opaque;
-    int val = 0, rc = 0;
-    socklen_t valsize = sizeof(val);
-    bool in_progress;
-    Error *err = NULL;
-
-    qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
-
-    do {
-        rc = qemu_getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &valsize);
-    } while (rc == -1 && errno == EINTR);
-
-    /* update rc to contain error */
-    if (!rc && val) {
-        rc = -1;
-        errno = val;
-    }
-
-    /* connect error */
-    if (rc < 0) {
-        error_setg_errno(&err, errno, "Error connecting to socket");
-        closesocket(s->fd);
-        s->fd = rc;
-    }
-
-    /* try to connect to the next address on the list */
-    if (s->current_addr) {
-        while (s->current_addr->ai_next != NULL && s->fd < 0) {
-            s->current_addr = s->current_addr->ai_next;
-            s->fd = inet_connect_addr(s->current_addr, &in_progress, s, NULL);
-            if (s->fd < 0) {
-                error_free(err);
-                err = NULL;
-                error_setg_errno(&err, errno, "Unable to start socket connect");
-            }
-            /* connect in progress */
-            if (in_progress) {
-                goto out;
-            }
-        }
-
-        freeaddrinfo(s->addr_list);
-    }
-
-    if (s->callback) {
-        s->callback(s->fd, err, s->opaque);
-    }
-    g_free(s);
-out:
-    error_free(err);
-}
-
-static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
-                             ConnectState *connect_state, Error **errp)
+static int inet_connect_addr(struct addrinfo *addr, Error **errp)
 {
     int sock, rc;
 
-    *in_progress = false;
-
     sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
     if (sock < 0) {
         error_setg_errno(errp, errno, "Failed to create socket");
         return -1;
     }
     socket_set_fast_reuse(sock);
-    if (connect_state != NULL) {
-        qemu_set_nonblock(sock);
-    }
+
     /* connect to peer */
     do {
         rc = 0;
@@ -432,15 +363,12 @@ static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
         }
     } while (rc == -EINTR);
 
-    if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
-        connect_state->fd = sock;
-        qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state);
-        *in_progress = true;
-    } else if (rc < 0) {
+    if (rc < 0) {
         error_setg_errno(errp, errno, "Failed to connect socket");
         closesocket(sock);
         return -1;
     }
+
     return sock;
 }
 
@@ -498,44 +426,24 @@ static struct addrinfo *inet_parse_connect_saddr(InetSocketAddress *saddr,
  *
  * @saddr: Inet socket address specification
  * @errp: set on error
- * @callback: callback function for non-blocking connect
- * @opaque: opaque for callback function
  *
  * Returns: -1 on error, file descriptor on success.
- *
- * If @callback is non-null, the connect is non-blocking.  If this
- * function succeeds, callback will be called when the connection
- * completes, with the file descriptor on success, or -1 on error.
  */
-int inet_connect_saddr(InetSocketAddress *saddr,
-                       NonBlockingConnectHandler *callback, void *opaque,
-                       Error **errp)
+int inet_connect_saddr(InetSocketAddress *saddr, Error **errp)
 {
     Error *local_err = NULL;
     struct addrinfo *res, *e;
     int sock = -1;
-    bool in_progress;
-    ConnectState *connect_state = NULL;
 
     res = inet_parse_connect_saddr(saddr, errp);
     if (!res) {
         return -1;
     }
 
-    if (callback != NULL) {
-        connect_state = g_malloc0(sizeof(*connect_state));
-        connect_state->addr_list = res;
-        connect_state->callback = callback;
-        connect_state->opaque = opaque;
-    }
-
     for (e = res; e != NULL; e = e->ai_next) {
         error_free(local_err);
         local_err = NULL;
-        if (connect_state != NULL) {
-            connect_state->current_addr = e;
-        }
-        sock = inet_connect_addr(e, &in_progress, connect_state, &local_err);
+        sock = inet_connect_addr(e, &local_err);
         if (sock >= 0) {
             break;
         }
@@ -543,15 +451,8 @@ int inet_connect_saddr(InetSocketAddress *saddr,
 
     if (sock < 0) {
         error_propagate(errp, local_err);
-    } else if (in_progress) {
-        /* wait_for_connect() will do the rest */
-        return sock;
-    } else {
-        if (callback) {
-            callback(sock, NULL, opaque);
-        }
     }
-    g_free(connect_state);
+
     freeaddrinfo(res);
     return sock;
 }
@@ -730,7 +631,7 @@ int inet_connect(const char *str, Error **errp)
     InetSocketAddress *addr = g_new(InetSocketAddress, 1);
 
     if (!inet_parse(addr, str, errp)) {
-        sock = inet_connect_saddr(addr, NULL, NULL, errp);
+        sock = inet_connect_saddr(addr, errp);
     }
     qapi_free_InetSocketAddress(addr);
     return sock;
@@ -763,21 +664,16 @@ static bool vsock_parse_vaddr_to_sockaddr(const VsockSocketAddress *vaddr,
     return true;
 }
 
-static int vsock_connect_addr(const struct sockaddr_vm *svm, bool *in_progress,
-                              ConnectState *connect_state, Error **errp)
+static int vsock_connect_addr(const struct sockaddr_vm *svm, Error **errp)
 {
     int sock, rc;
 
-    *in_progress = false;
-
     sock = qemu_socket(AF_VSOCK, SOCK_STREAM, 0);
     if (sock < 0) {
         error_setg_errno(errp, errno, "Failed to create socket");
         return -1;
     }
-    if (connect_state != NULL) {
-        qemu_set_nonblock(sock);
-    }
+
     /* connect to peer */
     do {
         rc = 0;
@@ -786,50 +682,26 @@ static int vsock_connect_addr(const struct sockaddr_vm *svm, bool *in_progress,
         }
     } while (rc == -EINTR);
 
-    if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
-        connect_state->fd = sock;
-        qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state);
-        *in_progress = true;
-    } else if (rc < 0) {
+    if (rc < 0) {
         error_setg_errno(errp, errno, "Failed to connect socket");
         closesocket(sock);
         return -1;
     }
+
     return sock;
 }
 
-static int vsock_connect_saddr(VsockSocketAddress *vaddr,
-                               NonBlockingConnectHandler *callback,
-                               void *opaque,
-                               Error **errp)
+static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp)
 {
     struct sockaddr_vm svm;
     int sock = -1;
-    bool in_progress;
-    ConnectState *connect_state = NULL;
 
     if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) {
         return -1;
     }
 
-    if (callback != NULL) {
-        connect_state = g_malloc0(sizeof(*connect_state));
-        connect_state->callback = callback;
-        connect_state->opaque = opaque;
-    }
+    sock = vsock_connect_addr(&svm, errp);
 
-    sock = vsock_connect_addr(&svm, &in_progress, connect_state, errp);
-    if (sock < 0) {
-        /* do nothing */
-    } else if (in_progress) {
-        /* wait_for_connect() will do the rest */
-        return sock;
-    } else {
-        if (callback) {
-            callback(sock, NULL, opaque);
-        }
-    }
-    g_free(connect_state);
     return sock;
 }
 
@@ -889,9 +761,7 @@ static void vsock_unsupported(Error **errp)
     error_setg(errp, "socket family AF_VSOCK unsupported");
 }
 
-static int vsock_connect_saddr(VsockSocketAddress *vaddr,
-                               NonBlockingConnectHandler *callback,
-                               void *opaque, Error **errp)
+static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp)
 {
     vsock_unsupported(errp);
     return -1;
@@ -994,12 +864,9 @@ err:
     return -1;
 }
 
-static int unix_connect_saddr(UnixSocketAddress *saddr,
-                              NonBlockingConnectHandler *callback, void *opaque,
-                              Error **errp)
+static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp)
 {
     struct sockaddr_un un;
-    ConnectState *connect_state = NULL;
     int sock, rc;
 
     if (saddr->path == NULL) {
@@ -1012,12 +879,6 @@ static int unix_connect_saddr(UnixSocketAddress *saddr,
         error_setg_errno(errp, errno, "Failed to create socket");
         return -1;
     }
-    if (callback != NULL) {
-        connect_state = g_malloc0(sizeof(*connect_state));
-        connect_state->callback = callback;
-        connect_state->opaque = opaque;
-        qemu_set_nonblock(sock);
-    }
 
     if (strlen(saddr->path) > sizeof(un.sun_path)) {
         error_setg(errp, "UNIX socket path '%s' is too long", saddr->path);
@@ -1038,29 +899,16 @@ static int unix_connect_saddr(UnixSocketAddress *saddr,
         }
     } while (rc == -EINTR);
 
-    if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
-        connect_state->fd = sock;
-        qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state);
-        return sock;
-    } else if (rc >= 0) {
-        /* non blocking socket immediate success, call callback */
-        if (callback != NULL) {
-            callback(sock, NULL, opaque);
-        }
-    }
-
     if (rc < 0) {
         error_setg_errno(errp, -rc, "Failed to connect socket %s",
                          saddr->path);
         goto err;
     }
 
-    g_free(connect_state);
     return sock;
 
  err:
     close(sock);
-    g_free(connect_state);
     return -1;
 }
 
@@ -1075,9 +923,7 @@ static int unix_listen_saddr(UnixSocketAddress *saddr,
     return -1;
 }
 
-static int unix_connect_saddr(UnixSocketAddress *saddr,
-                              NonBlockingConnectHandler *callback, void *opaque,
-                              Error **errp)
+static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp)
 {
     error_setg(errp, "unix sockets are not available on windows");
     errno = ENOTSUP;
@@ -1123,7 +969,7 @@ int unix_connect(const char *path, Error **errp)
 
     saddr = g_new0(UnixSocketAddress, 1);
     saddr->path = g_strdup(path);
-    sock = unix_connect_saddr(saddr, NULL, NULL, errp);
+    sock = unix_connect_saddr(saddr, errp);
     qapi_free_UnixSocketAddress(saddr);
     return sock;
 }
@@ -1168,30 +1014,25 @@ fail:
     return NULL;
 }
 
-int socket_connect(SocketAddress *addr, NonBlockingConnectHandler *callback,
-                   void *opaque, Error **errp)
+int socket_connect(SocketAddress *addr, Error **errp)
 {
     int fd;
 
     switch (addr->type) {
     case SOCKET_ADDRESS_TYPE_INET:
-        fd = inet_connect_saddr(&addr->u.inet, callback, opaque, errp);
+        fd = inet_connect_saddr(&addr->u.inet, errp);
         break;
 
     case SOCKET_ADDRESS_TYPE_UNIX:
-        fd = unix_connect_saddr(&addr->u.q_unix, callback, opaque, errp);
+        fd = unix_connect_saddr(&addr->u.q_unix, errp);
         break;
 
     case SOCKET_ADDRESS_TYPE_FD:
         fd = monitor_get_fd(cur_mon, addr->u.fd.str, errp);
-        if (fd >= 0 && callback) {
-            qemu_set_nonblock(fd);
-            callback(fd, NULL, opaque);
-        }
         break;
 
     case SOCKET_ADDRESS_TYPE_VSOCK:
-        fd = vsock_connect_saddr(&addr->u.vsock, callback, opaque, errp);
+        fd = vsock_connect_saddr(&addr->u.vsock, errp);
         break;
 
     default:
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PULL v1 7/9] io: fix typo in docs comment for qio_channel_read
  2017-09-05  9:22 [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Daniel P. Berrange
                   ` (5 preceding siblings ...)
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 6/9] util: remove the obsolete non-blocking connect Daniel P. Berrange
@ 2017-09-05  9:22 ` Daniel P. Berrange
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 8/9] io: add new qio_channel_{readv, writev, read, write}_all functions Daniel P. Berrange
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Daniel P. Berrange @ 2017-09-05  9:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Daniel P. Berrange

Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 include/io/channel.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/io/channel.h b/include/io/channel.h
index db9bb022a1..54f3dc252f 100644
--- a/include/io/channel.h
+++ b/include/io/channel.h
@@ -299,7 +299,7 @@ ssize_t qio_channel_writev(QIOChannel *ioc,
                            Error **errp);
 
 /**
- * qio_channel_readv:
+ * qio_channel_read:
  * @ioc: the channel object
  * @buf: the memory region to read data into
  * @buflen: the length of @buf
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PULL v1 8/9] io: add new qio_channel_{readv, writev, read, write}_all functions
  2017-09-05  9:22 [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Daniel P. Berrange
                   ` (6 preceding siblings ...)
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 7/9] io: fix typo in docs comment for qio_channel_read Daniel P. Berrange
@ 2017-09-05  9:22 ` Daniel P. Berrange
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 9/9] io: fix check for handshake completion in TLS test Daniel P. Berrange
  2017-09-05  9:37 ` [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Peter Maydell
  9 siblings, 0 replies; 13+ messages in thread
From: Daniel P. Berrange @ 2017-09-05  9:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Daniel P. Berrange

These functions wait until they are able to read / write the full
requested data buffer(s).

Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 include/io/channel.h       |  90 +++++++++++++++++++++++++++++++++++++++
 io/channel.c               |  94 +++++++++++++++++++++++++++++++++++++++++
 tests/io-channel-helpers.c | 102 ++++-----------------------------------------
 3 files changed, 193 insertions(+), 93 deletions(-)

diff --git a/include/io/channel.h b/include/io/channel.h
index 54f3dc252f..8f25893c45 100644
--- a/include/io/channel.h
+++ b/include/io/channel.h
@@ -269,6 +269,58 @@ ssize_t qio_channel_writev_full(QIOChannel *ioc,
                                 Error **errp);
 
 /**
+ * qio_channel_readv_all:
+ * @ioc: the channel object
+ * @iov: the array of memory regions to read data into
+ * @niov: the length of the @iov array
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Read data from the IO channel, storing it in the
+ * memory regions referenced by @iov. Each element
+ * in the @iov will be fully populated with data
+ * before the next one is used. The @niov parameter
+ * specifies the total number of elements in @iov.
+ *
+ * The function will wait for all requested data
+ * to be read, yielding from the current coroutine
+ * if required.
+ *
+ * If end-of-file occurs before all requested data
+ * has been read, an error will be reported.
+ *
+ * Returns: 0 if all bytes were read, or -1 on error
+ */
+int qio_channel_readv_all(QIOChannel *ioc,
+                          const struct iovec *iov,
+                          size_t niov,
+                          Error **errp);
+
+
+/**
+ * qio_channel_writev_all:
+ * @ioc: the channel object
+ * @iov: the array of memory regions to write data from
+ * @niov: the length of the @iov array
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Write data to the IO channel, reading it from the
+ * memory regions referenced by @iov. Each element
+ * in the @iov will be fully sent, before the next
+ * one is used. The @niov parameter specifies the
+ * total number of elements in @iov.
+ *
+ * The function will wait for all requested data
+ * to be written, yielding from the current coroutine
+ * if required.
+ *
+ * Returns: 0 if all bytes were written, or -1 on error
+ */
+int qio_channel_writev_all(QIOChannel *ioc,
+                           const struct iovec *iov,
+                           size_t niov,
+                           Error **erp);
+
+/**
  * qio_channel_readv:
  * @ioc: the channel object
  * @iov: the array of memory regions to read data into
@@ -331,6 +383,44 @@ ssize_t qio_channel_write(QIOChannel *ioc,
                           Error **errp);
 
 /**
+ * qio_channel_read_all:
+ * @ioc: the channel object
+ * @buf: the memory region to read data into
+ * @buflen: the number of bytes to @buf
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Reads @buflen bytes into @buf, possibly blocking or (if the
+ * channel is non-blocking) yielding from the current coroutine
+ * multiple times until the entire content is read. If end-of-file
+ * occurs it will return an error rather than a short-read. Otherwise
+ * behaves as qio_channel_read().
+ *
+ * Returns: 0 if all bytes were read, or -1 on error
+ */
+int qio_channel_read_all(QIOChannel *ioc,
+                         char *buf,
+                         size_t buflen,
+                         Error **errp);
+/**
+ * qio_channel_write_all:
+ * @ioc: the channel object
+ * @buf: the memory region to write data into
+ * @buflen: the number of bytes to @buf
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Writes @buflen bytes from @buf, possibly blocking or (if the
+ * channel is non-blocking) yielding from the current coroutine
+ * multiple times until the entire content is written.  Otherwise
+ * behaves as qio_channel_write().
+ *
+ * Returns: 0 if all bytes were written, or -1 on error
+ */
+int qio_channel_write_all(QIOChannel *ioc,
+                          const char *buf,
+                          size_t buflen,
+                          Error **errp);
+
+/**
  * qio_channel_set_blocking:
  * @ioc: the channel object
  * @enabled: the blocking flag state
diff --git a/io/channel.c b/io/channel.c
index 1cfb8b33a2..5e8c2f0a91 100644
--- a/io/channel.c
+++ b/io/channel.c
@@ -22,6 +22,7 @@
 #include "io/channel.h"
 #include "qapi/error.h"
 #include "qemu/main-loop.h"
+#include "qemu/iov.h"
 
 bool qio_channel_has_feature(QIOChannel *ioc,
                              QIOChannelFeature feature)
@@ -85,6 +86,79 @@ ssize_t qio_channel_writev_full(QIOChannel *ioc,
 }
 
 
+
+int qio_channel_readv_all(QIOChannel *ioc,
+                          const struct iovec *iov,
+                          size_t niov,
+                          Error **errp)
+{
+    int ret = -1;
+    struct iovec *local_iov = g_new(struct iovec, niov);
+    struct iovec *local_iov_head = local_iov;
+    unsigned int nlocal_iov = niov;
+
+    nlocal_iov = iov_copy(local_iov, nlocal_iov,
+                          iov, niov,
+                          0, iov_size(iov, niov));
+
+    while (nlocal_iov > 0) {
+        ssize_t len;
+        len = qio_channel_readv(ioc, local_iov, nlocal_iov, errp);
+        if (len == QIO_CHANNEL_ERR_BLOCK) {
+            qio_channel_wait(ioc, G_IO_IN);
+            continue;
+        } else if (len < 0) {
+            goto cleanup;
+        } else if (len == 0) {
+            error_setg(errp,
+                       "Unexpected end-of-file before all bytes were read");
+            goto cleanup;
+        }
+
+        iov_discard_front(&local_iov, &nlocal_iov, len);
+    }
+
+    ret = 0;
+
+ cleanup:
+    g_free(local_iov_head);
+    return ret;
+}
+
+int qio_channel_writev_all(QIOChannel *ioc,
+                           const struct iovec *iov,
+                           size_t niov,
+                           Error **errp)
+{
+    int ret = -1;
+    struct iovec *local_iov = g_new(struct iovec, niov);
+    struct iovec *local_iov_head = local_iov;
+    unsigned int nlocal_iov = niov;
+
+    nlocal_iov = iov_copy(local_iov, nlocal_iov,
+                          iov, niov,
+                          0, iov_size(iov, niov));
+
+    while (nlocal_iov > 0) {
+        ssize_t len;
+        len = qio_channel_writev(ioc, local_iov, nlocal_iov, errp);
+        if (len == QIO_CHANNEL_ERR_BLOCK) {
+            qio_channel_wait(ioc, G_IO_OUT);
+            continue;
+        }
+        if (len < 0) {
+            goto cleanup;
+        }
+
+        iov_discard_front(&local_iov, &nlocal_iov, len);
+    }
+
+    ret = 0;
+ cleanup:
+    g_free(local_iov_head);
+    return ret;
+}
+
 ssize_t qio_channel_readv(QIOChannel *ioc,
                           const struct iovec *iov,
                           size_t niov,
@@ -123,6 +197,26 @@ ssize_t qio_channel_write(QIOChannel *ioc,
 }
 
 
+int qio_channel_read_all(QIOChannel *ioc,
+                         char *buf,
+                         size_t buflen,
+                         Error **errp)
+{
+    struct iovec iov = { .iov_base = buf, .iov_len = buflen };
+    return qio_channel_readv_all(ioc, &iov, 1, errp);
+}
+
+
+int qio_channel_write_all(QIOChannel *ioc,
+                          const char *buf,
+                          size_t buflen,
+                          Error **errp)
+{
+    struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
+    return qio_channel_writev_all(ioc, &iov, 1, errp);
+}
+
+
 int qio_channel_set_blocking(QIOChannel *ioc,
                               bool enabled,
                               Error **errp)
diff --git a/tests/io-channel-helpers.c b/tests/io-channel-helpers.c
index 05e5579cf8..5430e1389d 100644
--- a/tests/io-channel-helpers.c
+++ b/tests/io-channel-helpers.c
@@ -21,6 +21,7 @@
 #include "qemu/osdep.h"
 #include "io-channel-helpers.h"
 #include "qapi/error.h"
+#include "qemu/iov.h"
 
 struct QIOChannelTest {
     QIOChannel *src;
@@ -37,77 +38,17 @@ struct QIOChannelTest {
 };
 
 
-static void test_skip_iovec(struct iovec **iov,
-                            size_t *niov,
-                            size_t skip,
-                            struct iovec *old)
-{
-    size_t offset = 0;
-    size_t i;
-
-    for (i = 0; i < *niov; i++) {
-        if (skip < (*iov)[i].iov_len) {
-            old->iov_len = (*iov)[i].iov_len;
-            old->iov_base = (*iov)[i].iov_base;
-
-            (*iov)[i].iov_len -= skip;
-            (*iov)[i].iov_base += skip;
-            break;
-        } else {
-            skip -= (*iov)[i].iov_len;
-
-            if (i == 0 && old->iov_base) {
-                (*iov)[i].iov_len = old->iov_len;
-                (*iov)[i].iov_base = old->iov_base;
-                old->iov_len = 0;
-                old->iov_base = NULL;
-            }
-
-            offset++;
-        }
-    }
-
-    *iov = *iov + offset;
-    *niov -= offset;
-}
-
-
 /* This thread sends all data using iovecs */
 static gpointer test_io_thread_writer(gpointer opaque)
 {
     QIOChannelTest *data = opaque;
-    struct iovec *iov = data->inputv;
-    size_t niov = data->niov;
-    struct iovec old = { 0 };
 
     qio_channel_set_blocking(data->src, data->blocking, NULL);
 
-    while (niov) {
-        ssize_t ret;
-        ret = qio_channel_writev(data->src,
-                                 iov,
-                                 niov,
-                                 &data->writeerr);
-        if (ret == QIO_CHANNEL_ERR_BLOCK) {
-            if (data->blocking) {
-                error_setg(&data->writeerr,
-                           "Unexpected I/O blocking");
-                break;
-            } else {
-                qio_channel_wait(data->src,
-                                 G_IO_OUT);
-                continue;
-            }
-        } else if (ret < 0) {
-            break;
-        } else if (ret == 0) {
-            error_setg(&data->writeerr,
-                       "Unexpected zero length write");
-            break;
-        }
-
-        test_skip_iovec(&iov, &niov, ret, &old);
-    }
+    qio_channel_writev_all(data->src,
+                           data->inputv,
+                           data->niov,
+                           &data->writeerr);
 
     return NULL;
 }
@@ -117,38 +58,13 @@ static gpointer test_io_thread_writer(gpointer opaque)
 static gpointer test_io_thread_reader(gpointer opaque)
 {
     QIOChannelTest *data = opaque;
-    struct iovec *iov = data->outputv;
-    size_t niov = data->niov;
-    struct iovec old = { 0 };
 
     qio_channel_set_blocking(data->dst, data->blocking, NULL);
 
-    while (niov) {
-        ssize_t ret;
-
-        ret = qio_channel_readv(data->dst,
-                                iov,
-                                niov,
-                                &data->readerr);
-
-        if (ret == QIO_CHANNEL_ERR_BLOCK) {
-            if (data->blocking) {
-                error_setg(&data->readerr,
-                           "Unexpected I/O blocking");
-                break;
-            } else {
-                qio_channel_wait(data->dst,
-                                 G_IO_IN);
-                continue;
-            }
-        } else if (ret < 0) {
-            break;
-        } else if (ret == 0) {
-            break;
-        }
-
-        test_skip_iovec(&iov, &niov, ret, &old);
-    }
+    qio_channel_readv_all(data->dst,
+                          data->outputv,
+                          data->niov,
+                          &data->readerr);
 
     return NULL;
 }
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PULL v1 9/9] io: fix check for handshake completion in TLS test
  2017-09-05  9:22 [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Daniel P. Berrange
                   ` (7 preceding siblings ...)
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 8/9] io: add new qio_channel_{readv, writev, read, write}_all functions Daniel P. Berrange
@ 2017-09-05  9:22 ` Daniel P. Berrange
  2017-09-05  9:37 ` [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Peter Maydell
  9 siblings, 0 replies; 13+ messages in thread
From: Daniel P. Berrange @ 2017-09-05  9:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Daniel P. Berrange

The TLS I/O channel test had mistakenly used && instead
of || when checking for handshake completion. As a
result it could terminate the handshake process before
it had actually completed. This was harmless before but
changes in GNUTLS 3.6.0 exposed this bug and caused the
test suite to fail.

Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 tests/test-io-channel-tls.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/test-io-channel-tls.c b/tests/test-io-channel-tls.c
index ff96877323..a210d01ba5 100644
--- a/tests/test-io-channel-tls.c
+++ b/tests/test-io-channel-tls.c
@@ -218,7 +218,7 @@ static void test_io_channel_tls(const void *opaque)
     mainloop = g_main_context_default();
     do {
         g_main_context_iteration(mainloop, TRUE);
-    } while (!clientHandshake.finished &&
+    } while (!clientHandshake.finished ||
              !serverHandshake.finished);
 
     g_assert(clientHandshake.failed == data->expectClientFail);
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05
  2017-09-05  9:22 [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Daniel P. Berrange
                   ` (8 preceding siblings ...)
  2017-09-05  9:22 ` [Qemu-devel] [PULL v1 9/9] io: fix check for handshake completion in TLS test Daniel P. Berrange
@ 2017-09-05  9:37 ` Peter Maydell
  2017-09-05  9:42   ` Peter Maydell
  2017-09-05  9:45   ` Daniel P. Berrange
  9 siblings, 2 replies; 13+ messages in thread
From: Peter Maydell @ 2017-09-05  9:37 UTC (permalink / raw)
  To: Daniel P. Berrange; +Cc: QEMU Developers

On 5 September 2017 at 10:22, Daniel P. Berrange <berrange@redhat.com> wrote:
> The following changes since commit 32f0f68bb77289b75a82925f712bb52e16eac3ba:
>
>   Merge remote-tracking branch 'remotes/ehabkost/tags/x86-and-machine-pull-request' into staging (2017-09-01 17:28:54 +0100)
>
> are available in the git repository at:
>
>   git://github.com/berrange/qemu tags/pull-qio-20170905-1
>
> for you to fetch changes up to 33fb97121573985b4a57306b8abdb9dd992061fa:
>
>   io: fix check for handshake completion in TLS test (2017-09-05 10:20:28 +0100)
>
> ----------------------------------------------------------------
> Merge QEMU I/O 2017/09/05 v1
>
> ----------------------------------------------------------------

I get a build failure with this I'm afraid:

FreeBSD:
/root/qemu/tests/test-listen.c:53:19: error: use of undeclared
identifier 'EAI_ADDRFAMILY'
        if (rc == EAI_ADDRFAMILY ||
                  ^

and test-listen fails on my x86-64 Linux box:
  GTESTER tests/test-listen
** Failed to assign a port to thread 0 (errno = 98)
** Failed to assign a port to thread 1 (errno = 98)
** Failed to assign a port to thread 2 (errno = 98)
** Failed to assign a port to thread 3 (errno = 98)
** Failed to assign a port to thread 4 (errno = 98)
** Failed to assign a port to thread 5 (errno = 98)
** Failed to assign a port to thread 6 (errno = 98)
[snip 7..96 same message]
** Failed to assign a port to thread 97 (errno = 98)
** Failed to assign a port to thread 98 (errno = 98)
** Failed to assign a port to thread 99 (errno = 98)
** Failed to assign a port to thread 100 (errno = 110)
** Failed to assign a port to thread 101 (errno = 110)
** Failed to assign a port to thread 102 (errno = 110)
** Failed to assign a port to thread 103 (errno = 110)
[snip more with =110 message]
** Failed to assign a port to thread 198 (errno = 110)
** Failed to assign a port to thread 199 (errno = 110)
**
ERROR:/home/petmay01/linaro/qemu-for-merges/tests/test-listen.c:195:listen_compete_nthr:
assertion failed (failed_listens == 0): (200 == 0)
GTester: last random seed: R02S501c6ff1c5ff42cf11b1318e0de42bc5

(98 is EADDRINUSE and 110 is ETIMEDOUT I think.)

aarch64 host fails sort of similarly:
TEST: tests/test-listen... (pid=12632)
  /socket/listen-serial/ipv4:                                          OK
  /socket/listen-serial/ipv6:
** Failed to assign a port to th
read 0 (errno = 98)
** Failed to assign a port to thread 1 (errno = 98)
** Failed to assign a port to thread 2 (errno = 98)
[snip]
** Failed to assign a port to thread 199 (errno = 98)
**
ERROR:/home/peter.maydell/qemu/tests/test-listen.c:195:listen_compete_nthr:
assertion failed (failed_listens == 0): (200 == 0)
FAIL
GTester: last random seed: R02Sbd34929fe0b3304c2873c42c94643648
(pid=12634)
  /socket/listen-serial/generic:                                       OK
  /socket/listen-compete/ipv4:                                         OK
  /socket/listen-compete/ipv6:                                         OK
  /socket/listen-compete/generic:                                      OK
FAIL: tests/test-listen

except that it's errno 98 all the way through.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05
  2017-09-05  9:37 ` [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Peter Maydell
@ 2017-09-05  9:42   ` Peter Maydell
  2017-09-05  9:45   ` Daniel P. Berrange
  1 sibling, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2017-09-05  9:42 UTC (permalink / raw)
  To: Daniel P. Berrange; +Cc: QEMU Developers

On 5 September 2017 at 10:37, Peter Maydell <peter.maydell@linaro.org> wrote:
> and test-listen fails on my x86-64 Linux box:

OpenBSD fails too, but only starting at thread 124, and
it fails like this for all the tests whereas Linux
only failed on the ipv6 test:

TEST: tests/test-listen... (pid=12010)
  /socket/listen-serial/ipv4:
** Failed to assign a port to thread 124 (errno = 48)
** Failed to assign a port to thread 125 (errno = 48)
** Failed to assign a port to thread 126 (errno = 48)
** Failed to assign a port to thread 127 (errno = 48)
** Failed to assign a port to thread 128 (errno = 48)
** Failed to assign a port to thread 129 (errno = 48)
** Failed to assign a port to thread 130 (errno = 48)
** Failed to assign a port to thread 131 (errno = 48)
** Failed to assign a port to thread 132 (errno = 48)
[snip]
** Failed to assign a port to thread 197 (errno = 48)
** Failed to assign a port to thread 198 (errno = 48)
** Failed to assign a port to thread 199 (errno = 48)
**
ERROR:/home/qemu/tests/test-listen.c:195:listen_compete_nthr:
assertion failed (failed_listens == 0): (76 == 0)
FAIL
GTester: last random seed: R02S5df2be6aaaf10151ac566254ab2f7e88
(pid=37081)
  /socket/listen-serial/ipv6:
** Failed to assign a port to thread 124 (errno = 48)
** Failed to assign a port to thread 125 (errno = 48)
** Failed to assign a port to thread 126 (errno = 48)
** Failed to assign a port to thread 127 (errno = 48)
[snip]
** Failed to assign a port to thread 198 (errno = 48)
** Failed to assign a port to thread 199 (errno = 48)
**
ERROR:/home/qemu/tests/test-listen.c:195:listen_compete_nthr:
assertion failed (failed_listens == 0): (76 == 0)
FAIL
GTester: last random seed: R02Sa41cf200664d43a074a38d7fff7b5393
(pid=93074)
  /socket/listen-serial/generic:
** Failed to assign a port to thread 124 (errno = 48)
** Failed to assign a port to thread 125 (errno = 48)
** Failed to assign a port to thread 126 (errno = 48)
** Failed to assign a port to thread 127 (errno = 48)
[snip]
** Failed to assign a port to thread 198 (errno = 48)
** Failed to assign a port to thread 199 (errno = 48)
**
ERROR:/home/qemu/tests/test-listen.c:195:listen_compete_nthr:
assertion failed (failed_listens == 0): (76 == 0)
FAIL
GTester: last random seed: R02S072bffdb79ddc59e35f0b9c1f8b8f69f
(pid=56289)
  /socket/listen-compete/ipv4:
** Failed to assign a port to thread 124 (errno = 24)
** Failed to assign a port to thread 127 (errno = 24)
** Failed to assign a port to thread 128 (errno = 24)
** Failed to assign a port to thread 129 (errno = 24)
** Failed to assign a port to thread 130 (errno = 24)
[etc etc]

thanks
-- PMM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05
  2017-09-05  9:37 ` [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Peter Maydell
  2017-09-05  9:42   ` Peter Maydell
@ 2017-09-05  9:45   ` Daniel P. Berrange
  1 sibling, 0 replies; 13+ messages in thread
From: Daniel P. Berrange @ 2017-09-05  9:45 UTC (permalink / raw)
  To: Peter Maydell, Knut Omang; +Cc: QEMU Developers

On Tue, Sep 05, 2017 at 10:37:08AM +0100, Peter Maydell wrote:
> On 5 September 2017 at 10:22, Daniel P. Berrange <berrange@redhat.com> wrote:
> > The following changes since commit 32f0f68bb77289b75a82925f712bb52e16eac3ba:
> >
> >   Merge remote-tracking branch 'remotes/ehabkost/tags/x86-and-machine-pull-request' into staging (2017-09-01 17:28:54 +0100)
> >
> > are available in the git repository at:
> >
> >   git://github.com/berrange/qemu tags/pull-qio-20170905-1
> >
> > for you to fetch changes up to 33fb97121573985b4a57306b8abdb9dd992061fa:
> >
> >   io: fix check for handshake completion in TLS test (2017-09-05 10:20:28 +0100)
> >
> > ----------------------------------------------------------------
> > Merge QEMU I/O 2017/09/05 v1
> >
> > ----------------------------------------------------------------
> 
> I get a build failure with this I'm afraid:
> 
> FreeBSD:
> /root/qemu/tests/test-listen.c:53:19: error: use of undeclared
> identifier 'EAI_ADDRFAMILY'
>         if (rc == EAI_ADDRFAMILY ||
>                   ^

Opps, ok, that's an easy fix.

> and test-listen fails on my x86-64 Linux box:
>   GTESTER tests/test-listen
> ** Failed to assign a port to thread 0 (errno = 98)
> ** Failed to assign a port to thread 1 (errno = 98)
> ** Failed to assign a port to thread 2 (errno = 98)
> ** Failed to assign a port to thread 3 (errno = 98)
> ** Failed to assign a port to thread 4 (errno = 98)
> ** Failed to assign a port to thread 5 (errno = 98)
> ** Failed to assign a port to thread 6 (errno = 98)
> [snip 7..96 same message]
> ** Failed to assign a port to thread 97 (errno = 98)
> ** Failed to assign a port to thread 98 (errno = 98)
> ** Failed to assign a port to thread 99 (errno = 98)
> ** Failed to assign a port to thread 100 (errno = 110)
> ** Failed to assign a port to thread 101 (errno = 110)
> ** Failed to assign a port to thread 102 (errno = 110)
> ** Failed to assign a port to thread 103 (errno = 110)
> [snip more with =110 message]
> ** Failed to assign a port to thread 198 (errno = 110)
> ** Failed to assign a port to thread 199 (errno = 110)
> **
> ERROR:/home/petmay01/linaro/qemu-for-merges/tests/test-listen.c:195:listen_compete_nthr:
> assertion failed (failed_listens == 0): (200 == 0)
> GTester: last random seed: R02S501c6ff1c5ff42cf11b1318e0de42bc5
> 
> (98 is EADDRINUSE and 110 is ETIMEDOUT I think.)
> 
> aarch64 host fails sort of similarly:
> TEST: tests/test-listen... (pid=12632)
>   /socket/listen-serial/ipv4:                                          OK
>   /socket/listen-serial/ipv6:
> ** Failed to assign a port to th
> read 0 (errno = 98)
> ** Failed to assign a port to thread 1 (errno = 98)
> ** Failed to assign a port to thread 2 (errno = 98)
> [snip]
> ** Failed to assign a port to thread 199 (errno = 98)
> **
> ERROR:/home/peter.maydell/qemu/tests/test-listen.c:195:listen_compete_nthr:
> assertion failed (failed_listens == 0): (200 == 0)
> FAIL
> GTester: last random seed: R02Sbd34929fe0b3304c2873c42c94643648
> (pid=12634)
>   /socket/listen-serial/generic:                                       OK
>   /socket/listen-compete/ipv4:                                         OK
>   /socket/listen-compete/ipv6:                                         OK
>   /socket/listen-compete/generic:                                      OK
> FAIL: tests/test-listen
> 
> except that it's errno 98 all the way through.

Knut,  do you have any thoughts on why Peter would see such failures
in this test ?

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] 13+ messages in thread

end of thread, other threads:[~2017-09-05  9:46 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-05  9:22 [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Daniel P. Berrange
2017-09-05  9:22 ` [Qemu-devel] [PULL v1 1/9] io: fix temp directory used by test-io-channel-tls test Daniel P. Berrange
2017-09-05  9:22 ` [Qemu-devel] [PULL v1 2/9] tests: Add test-listen - a stress test for QEMU socket listen Daniel P. Berrange
2017-09-05  9:22 ` [Qemu-devel] [PULL v1 3/9] sockets: factor out a new try_bind() function Daniel P. Berrange
2017-09-05  9:22 ` [Qemu-devel] [PULL v1 4/9] sockets: factor out create_fast_reuse_socket Daniel P. Berrange
2017-09-05  9:22 ` [Qemu-devel] [PULL v1 5/9] sockets: Handle race condition between binds to the same port Daniel P. Berrange
2017-09-05  9:22 ` [Qemu-devel] [PULL v1 6/9] util: remove the obsolete non-blocking connect Daniel P. Berrange
2017-09-05  9:22 ` [Qemu-devel] [PULL v1 7/9] io: fix typo in docs comment for qio_channel_read Daniel P. Berrange
2017-09-05  9:22 ` [Qemu-devel] [PULL v1 8/9] io: add new qio_channel_{readv, writev, read, write}_all functions Daniel P. Berrange
2017-09-05  9:22 ` [Qemu-devel] [PULL v1 9/9] io: fix check for handshake completion in TLS test Daniel P. Berrange
2017-09-05  9:37 ` [Qemu-devel] [PULL v1 0/9] Merge QEMU I/O 2017/09/05 Peter Maydell
2017-09-05  9:42   ` Peter Maydell
2017-09-05  9:45   ` Daniel P. Berrange

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.