All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH for-2.7 0/2] Fix net socket connect regressions
@ 2016-08-23  9:45 Marc-André Lureau
  2016-08-23  9:45 ` [Qemu-devel] [PATCH for-2.7 1/2] net: fix socket connect Marc-André Lureau
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Marc-André Lureau @ 2016-08-23  9:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: pbonzini, jasowang, berrange, ashijeetacharya, crobinso,
	Marc-André Lureau

Hi,

Commit 7e8449594c929 introduced multiple regressions. The most
important is that the socket is actually not the one connected, due to
wrong usage of socket_connect(). I fixed that along with some leak
fixes, that could eventually be splitted.

Secondly, connect is no longer non-blocking. The second patch is my
attempt to fix it.

Fixes:
https://bugzilla.redhat.com/show_bug.cgi?id=1368447

Please review asap

Marc-André Lureau (2):
  net: fix socket connect
  net: make socket connect non-blocking again

 net/socket.c | 102 ++++++++++++++++++++++++++++++++++-------------------------
 1 file changed, 59 insertions(+), 43 deletions(-)

-- 
2.9.0

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

* [Qemu-devel] [PATCH for-2.7 1/2] net: fix socket connect
  2016-08-23  9:45 [Qemu-devel] [PATCH for-2.7 0/2] Fix net socket connect regressions Marc-André Lureau
@ 2016-08-23  9:45 ` Marc-André Lureau
  2016-08-23  9:45 ` [Qemu-devel] [PATCH for-2.7 2/2] net: make socket connect non-blocking again Marc-André Lureau
  2016-08-30 12:07 ` [Qemu-devel] [PATCH for-2.7 0/2] Fix net socket connect regressions Paolo Bonzini
  2 siblings, 0 replies; 7+ messages in thread
From: Marc-André Lureau @ 2016-08-23  9:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: pbonzini, jasowang, berrange, ashijeetacharya, crobinso,
	Marc-André Lureau

Commit 7e8449594c929 changed net socket code to use socket_*() functions
from include/qemu/sockets.h. However, the change broke the connection
part, because socket_connect() returns a connected socket that is
being ignored. Use socket_connect() return value appropriately and fix
leaks on error path.

Note that after this change, the function is still blocking.

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1368447

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 net/socket.c | 54 +++++++++++++++++++++++-------------------------------
 1 file changed, 23 insertions(+), 31 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index 17e635d..645bcb0 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -501,6 +501,7 @@ static int net_socket_listen_init(NetClientState *peer,
 
     ret = socket_listen(saddr, &local_error);
     if (ret < 0) {
+        qapi_free_SocketAddress(saddr);
         error_report_err(local_error);
         return -1;
     }
@@ -522,9 +523,9 @@ static int net_socket_connect_init(NetClientState *peer,
                                    const char *host_str)
 {
     NetSocketState *s;
-    int fd, connected, ret;
-    char *addr_str;
-    SocketAddress *saddr;
+    int fd = -1, ret = -1;
+    char *addr_str = NULL;
+    SocketAddress *saddr = NULL;
     Error *local_error = NULL;
 
     saddr = socket_parse(host_str, &local_error);
@@ -533,45 +534,36 @@ static int net_socket_connect_init(NetClientState *peer,
         return -1;
     }
 
-    fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
+    fd = socket_connect(saddr, &local_error, NULL, NULL);
     if (fd < 0) {
-        perror("socket");
-        return -1;
+        error_report_err(local_error);
+        goto end;
     }
+
     qemu_set_nonblock(fd);
-    connected = 0;
-    for(;;) {
-        ret = socket_connect(saddr, &local_error, NULL, NULL);
-        if (ret < 0) {
-            if (errno == EINTR || errno == EWOULDBLOCK) {
-                /* continue */
-            } else if (errno == EINPROGRESS ||
-                       errno == EALREADY ||
-                       errno == EINVAL) {
-                break;
-            } else {
-                error_report_err(local_error);
-                closesocket(fd);
-                return -1;
-            }
-        } else {
-            connected = 1;
-            break;
-        }
+
+    s = net_socket_fd_init(peer, model, name, fd, true);
+    if (!s) {
+        goto end;
     }
-    s = net_socket_fd_init(peer, model, name, fd, connected);
-    if (!s)
-        return -1;
 
     addr_str = socket_address_to_string(saddr, &local_error);
-    if (addr_str == NULL)
-        return -1;
+    if (addr_str == NULL) {
+        error_report_err(local_error);
+        goto end;
+    }
 
     snprintf(s->nc.info_str, sizeof(s->nc.info_str),
              "socket: connect to %s", addr_str);
+    ret = 0;
+
+end:
+    if (ret == -1 && fd >= 0) {
+        closesocket(fd);
+    }
     qapi_free_SocketAddress(saddr);
     g_free(addr_str);
-    return 0;
+    return ret;
 }
 
 static int net_socket_mcast_init(NetClientState *peer,
-- 
2.9.0

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

* [Qemu-devel] [PATCH for-2.7 2/2] net: make socket connect non-blocking again
  2016-08-23  9:45 [Qemu-devel] [PATCH for-2.7 0/2] Fix net socket connect regressions Marc-André Lureau
  2016-08-23  9:45 ` [Qemu-devel] [PATCH for-2.7 1/2] net: fix socket connect Marc-André Lureau
@ 2016-08-23  9:45 ` Marc-André Lureau
  2016-08-23 10:43   ` Cao jin
  2016-08-30 12:07 ` [Qemu-devel] [PATCH for-2.7 0/2] Fix net socket connect regressions Paolo Bonzini
  2 siblings, 1 reply; 7+ messages in thread
From: Marc-André Lureau @ 2016-08-23  9:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: pbonzini, jasowang, berrange, ashijeetacharya, crobinso,
	Marc-André Lureau

Since commit 7e8449594c929, the socket connect code is blocking, because
calling socket_connect() without callback is blocking. Make it
non-blocking by adding a callback. Unfortunately, the callback needs
many local variables that are not easy to get rid of (it can't easily
create the qemu_new_net_client() earlier). By adding the callback, the
socket is also made non-blocking. If the socket attempt succeeded
immediately, the callback is still being called.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 net/socket.c | 82 +++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 53 insertions(+), 29 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index 645bcb0..982c8de 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -517,53 +517,77 @@ static int net_socket_listen_init(NetClientState *peer,
     return 0;
 }
 
-static int net_socket_connect_init(NetClientState *peer,
-                                   const char *model,
-                                   const char *name,
-                                   const char *host_str)
+typedef struct {
+    NetClientState *peer;
+    SocketAddress *saddr;
+    char *model;
+    char *name;
+} socket_connect_data;
+
+static void socket_connect_data_free(socket_connect_data *c)
 {
+    qapi_free_SocketAddress(c->saddr);
+    g_free(c->model);
+    g_free(c->name);
+    g_free(c);
+}
+
+static void net_socket_connected(int fd, Error *err, void *opaque)
+{
+    socket_connect_data *c = opaque;
     NetSocketState *s;
-    int fd = -1, ret = -1;
     char *addr_str = NULL;
-    SocketAddress *saddr = NULL;
     Error *local_error = NULL;
 
-    saddr = socket_parse(host_str, &local_error);
-    if (saddr == NULL) {
-        error_report_err(local_error);
-        return -1;
-    }
-
-    fd = socket_connect(saddr, &local_error, NULL, NULL);
-    if (fd < 0) {
+    addr_str = socket_address_to_string(c->saddr, &local_error);
+    if (addr_str == NULL) {
         error_report_err(local_error);
+        closesocket(fd);
         goto end;
     }
 
-    qemu_set_nonblock(fd);
-
-    s = net_socket_fd_init(peer, model, name, fd, true);
+    s = net_socket_fd_init(c->peer, c->model, c->name, fd, true);
     if (!s) {
-        goto end;
-    }
-
-    addr_str = socket_address_to_string(saddr, &local_error);
-    if (addr_str == NULL) {
-        error_report_err(local_error);
+        closesocket(fd);
         goto end;
     }
 
     snprintf(s->nc.info_str, sizeof(s->nc.info_str),
              "socket: connect to %s", addr_str);
-    ret = 0;
 
 end:
-    if (ret == -1 && fd >= 0) {
-        closesocket(fd);
-    }
-    qapi_free_SocketAddress(saddr);
     g_free(addr_str);
-    return ret;
+    socket_connect_data_free(c);
+}
+
+static int net_socket_connect_init(NetClientState *peer,
+                                   const char *model,
+                                   const char *name,
+                                   const char *host_str)
+{
+    socket_connect_data *c = g_new0(socket_connect_data, 1);
+    int fd = -1;
+    Error *local_error = NULL;
+
+    c->peer = peer;
+    c->model = g_strdup(model);
+    c->name = g_strdup(name);
+    c->saddr = socket_parse(host_str, &local_error);
+    if (c->saddr == NULL) {
+        goto err;
+    }
+
+    fd = socket_connect(c->saddr, &local_error, net_socket_connected, c);
+    if (fd < 0) {
+        goto err;
+    }
+
+    return 0;
+
+err:
+    error_report_err(local_error);
+    socket_connect_data_free(c);
+    return -1;
 }
 
 static int net_socket_mcast_init(NetClientState *peer,
-- 
2.9.0

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

* Re: [Qemu-devel] [PATCH for-2.7 2/2] net: make socket connect non-blocking again
  2016-08-23  9:45 ` [Qemu-devel] [PATCH for-2.7 2/2] net: make socket connect non-blocking again Marc-André Lureau
@ 2016-08-23 10:43   ` Cao jin
  2016-08-23 13:13     ` Daniel P. Berrange
  0 siblings, 1 reply; 7+ messages in thread
From: Cao jin @ 2016-08-23 10:43 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel
  Cc: jasowang, crobinso, ashijeetacharya, pbonzini, Daniel P. Berrange

Hi,
I just noticed you still using the old-style non-blocking connect(which 
will still block when query DNS), which will be removed (suggested by 
Daniel), but the patch is still on the way. So I guess maybe you should 
switch to QIOChannel way.

FYI:
http://lists.nongnu.org/archive/html/qemu-devel/2016-07/msg06386.html
http://lists.nongnu.org/archive/html/qemu-devel/2016-08/msg00046.html

     Cao jin

On 08/23/2016 05:45 PM, Marc-André Lureau wrote:
> Since commit 7e8449594c929, the socket connect code is blocking, because
> calling socket_connect() without callback is blocking. Make it
> non-blocking by adding a callback. Unfortunately, the callback needs
> many local variables that are not easy to get rid of (it can't easily
> create the qemu_new_net_client() earlier). By adding the callback, the
> socket is also made non-blocking. If the socket attempt succeeded
> immediately, the callback is still being called.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>   net/socket.c | 82 +++++++++++++++++++++++++++++++++++++++---------------------
>   1 file changed, 53 insertions(+), 29 deletions(-)
>

> +
> +static int net_socket_connect_init(NetClientState *peer,
> +                                   const char *model,
> +                                   const char *name,
> +                                   const char *host_str)
> +{
> +    socket_connect_data *c = g_new0(socket_connect_data, 1);
> +    int fd = -1;
> +    Error *local_error = NULL;
> +
> +    c->peer = peer;
> +    c->model = g_strdup(model);
> +    c->name = g_strdup(name);
> +    c->saddr = socket_parse(host_str, &local_error);
> +    if (c->saddr == NULL) {
> +        goto err;
> +    }
> +
> +    fd = socket_connect(c->saddr, &local_error, net_socket_connected, c);
> +    if (fd < 0) {
> +        goto err;
> +    }
> +
> +    return 0;
> +
> +err:
> +    error_report_err(local_error);
> +    socket_connect_data_free(c);
> +    return -1;
>   }
>
>   static int net_socket_mcast_init(NetClientState *peer,
>

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

* Re: [Qemu-devel] [PATCH for-2.7 2/2] net: make socket connect non-blocking again
  2016-08-23 10:43   ` Cao jin
@ 2016-08-23 13:13     ` Daniel P. Berrange
  2016-08-23 13:33       ` Marc-André Lureau
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel P. Berrange @ 2016-08-23 13:13 UTC (permalink / raw)
  To: Cao jin
  Cc: Marc-André Lureau, qemu-devel, jasowang, crobinso,
	ashijeetacharya, pbonzini

On Tue, Aug 23, 2016 at 06:43:54PM +0800, Cao jin wrote:
> Hi,
> I just noticed you still using the old-style non-blocking connect(which will
> still block when query DNS), which will be removed (suggested by Daniel),
> but the patch is still on the way. So I guess maybe you should switch to
> QIOChannel way.
> 
> FYI:
> http://lists.nongnu.org/archive/html/qemu-devel/2016-07/msg06386.html
> http://lists.nongnu.org/archive/html/qemu-devel/2016-08/msg00046.html

Yes, switching to QIOChannel would be good, but that is certainly not
something that's acceptable for 2.7.0. We need Marc-André's fix in the
short term for this release. If someone wants to do a QIOChannel
conversion for 2.8.0/2.9.0/etc that's an option...


Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

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

* Re: [Qemu-devel] [PATCH for-2.7 2/2] net: make socket connect non-blocking again
  2016-08-23 13:13     ` Daniel P. Berrange
@ 2016-08-23 13:33       ` Marc-André Lureau
  0 siblings, 0 replies; 7+ messages in thread
From: Marc-André Lureau @ 2016-08-23 13:33 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Cao jin, Marc-André Lureau, qemu-devel, jasowang, crobinso,
	ashijeetacharya, pbonzini

[-- Attachment #1: Type: text/plain, Size: 1137 bytes --]

Hi

----- Original Message -----
> On Tue, Aug 23, 2016 at 06:43:54PM +0800, Cao jin wrote:
> > Hi,
> > I just noticed you still using the old-style non-blocking connect(which
> > will
> > still block when query DNS), which will be removed (suggested by Daniel),
> > but the patch is still on the way. So I guess maybe you should switch to
> > QIOChannel way.
> > 
> > FYI:
> > http://lists.nongnu.org/archive/html/qemu-devel/2016-07/msg06386.html
> > http://lists.nongnu.org/archive/html/qemu-devel/2016-08/msg00046.html
> 
> Yes, switching to QIOChannel would be good, but that is certainly not
> something that's acceptable for 2.7.0. We need Marc-André's fix in the
> short term for this release. If someone wants to do a QIOChannel
> conversion for 2.8.0/2.9.0/etc that's an option...

After looking at this a bit, it would need significant effort for net/socket to switch fully to qiochannel, so it's certainly not for 2.7. However, we could use it just for the connect step for now (see attached patch)

(tbh, I am not sure how well that net/socket async code is being handled in case of cancellation etc..)

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-net-make-socket-connect-non-blocking-again.patch --]
[-- Type: text/x-patch; name=0001-net-make-socket-connect-non-blocking-again.patch, Size: 4437 bytes --]

From ad81f6d913bdb09b6f7c781c1e55ac42228f7c4f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Tue, 23 Aug 2016 13:33:30 +0400
Subject: [PATCH] net: make socket connect non-blocking again
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Since commit 7e8449594c929, the socket connect code is blocking, because
calling socket_connect() without callback is blocking. Make it
non-blocking by adding a callback. Unfortunately, the callback needs
many local variables that are not easy to get rid of (it can't easily
create the qemu_new_net_client() earlier). By adding the callback, the
socket is also made non-blocking. If the socket attempt succeeded
immediately, the callback is still being called.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 net/socket.c | 91 ++++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 61 insertions(+), 30 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index 645bcb0..ca0c0b7 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -33,6 +33,7 @@
 #include "qemu/sockets.h"
 #include "qemu/iov.h"
 #include "qemu/main-loop.h"
+#include "io/channel-socket.h"
 
 typedef struct NetSocketState {
     NetClientState nc;
@@ -517,53 +518,83 @@ static int net_socket_listen_init(NetClientState *peer,
     return 0;
 }
 
-static int net_socket_connect_init(NetClientState *peer,
-                                   const char *model,
-                                   const char *name,
-                                   const char *host_str)
+typedef struct {
+    QIOChannelSocket *qio_socket;
+    NetClientState *peer;
+    SocketAddress *saddr;
+    char *model;
+    char *name;
+} socket_connect_data;
+
+static void socket_connect_data_free(void *data)
 {
+    socket_connect_data *c = data;
+
+    qapi_free_SocketAddress(c->saddr);
+    object_unref(OBJECT(c->qio_socket));
+    g_free(c->model);
+    g_free(c->name);
+    g_free(c);
+}
+
+static void net_socket_connect_cb(Object *source,
+                                  Error *err,
+                                  gpointer opaque)
+{
+    socket_connect_data *c = opaque;
+    int fd;
     NetSocketState *s;
-    int fd = -1, ret = -1;
     char *addr_str = NULL;
-    SocketAddress *saddr = NULL;
     Error *local_error = NULL;
 
-    saddr = socket_parse(host_str, &local_error);
-    if (saddr == NULL) {
-        error_report_err(local_error);
-        return -1;
-    }
-
-    fd = socket_connect(saddr, &local_error, NULL, NULL);
-    if (fd < 0) {
+    addr_str = socket_address_to_string(c->saddr, &local_error);
+    if (addr_str == NULL) {
         error_report_err(local_error);
-        goto end;
+        return;
     }
 
-    qemu_set_nonblock(fd);
-
-    s = net_socket_fd_init(peer, model, name, fd, true);
+    fd = c->qio_socket->fd;
+    c->qio_socket->fd = -1;
+    s = net_socket_fd_init(c->peer, c->model, c->name, fd, true);
     if (!s) {
-        goto end;
-    }
-
-    addr_str = socket_address_to_string(saddr, &local_error);
-    if (addr_str == NULL) {
-        error_report_err(local_error);
+        closesocket(fd);
         goto end;
     }
 
     snprintf(s->nc.info_str, sizeof(s->nc.info_str),
              "socket: connect to %s", addr_str);
-    ret = 0;
 
 end:
-    if (ret == -1 && fd >= 0) {
-        closesocket(fd);
-    }
-    qapi_free_SocketAddress(saddr);
     g_free(addr_str);
-    return ret;
+}
+
+static int net_socket_connect_init(NetClientState *peer,
+                                   const char *model,
+                                   const char *name,
+                                   const char *host_str)
+{
+    socket_connect_data *c = g_new0(socket_connect_data, 1);
+    Error *local_error = NULL;
+
+    c->qio_socket = qio_channel_socket_new();
+    c->peer = peer;
+    c->model = g_strdup(model);
+    c->name = g_strdup(name);
+    c->saddr = socket_parse(host_str, &local_error);
+    if (c->saddr == NULL) {
+        goto err;
+    }
+
+    qio_channel_socket_connect_async(c->qio_socket, c->saddr,
+                                     net_socket_connect_cb,
+                                     c, socket_connect_data_free);
+
+    return 0;
+
+err:
+    error_report_err(local_error);
+    socket_connect_data_free(c);
+    return -1;
 }
 
 static int net_socket_mcast_init(NetClientState *peer,
-- 
2.9.0


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

* Re: [Qemu-devel] [PATCH for-2.7 0/2] Fix net socket connect regressions
  2016-08-23  9:45 [Qemu-devel] [PATCH for-2.7 0/2] Fix net socket connect regressions Marc-André Lureau
  2016-08-23  9:45 ` [Qemu-devel] [PATCH for-2.7 1/2] net: fix socket connect Marc-André Lureau
  2016-08-23  9:45 ` [Qemu-devel] [PATCH for-2.7 2/2] net: make socket connect non-blocking again Marc-André Lureau
@ 2016-08-30 12:07 ` Paolo Bonzini
  2 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2016-08-30 12:07 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel
  Cc: jasowang, berrange, ashijeetacharya, crobinso



On 23/08/2016 11:45, Marc-André Lureau wrote:
> Hi,
> 
> Commit 7e8449594c929 introduced multiple regressions. The most
> important is that the socket is actually not the one connected, due to
> wrong usage of socket_connect(). I fixed that along with some leak
> fixes, that could eventually be splitted.
> 
> Secondly, connect is no longer non-blocking. The second patch is my
> attempt to fix it.
> 
> Fixes:
> https://bugzilla.redhat.com/show_bug.cgi?id=1368447

I'll send a revert, and your patch for 2.8.

Paolo

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

end of thread, other threads:[~2016-08-30 12:07 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-23  9:45 [Qemu-devel] [PATCH for-2.7 0/2] Fix net socket connect regressions Marc-André Lureau
2016-08-23  9:45 ` [Qemu-devel] [PATCH for-2.7 1/2] net: fix socket connect Marc-André Lureau
2016-08-23  9:45 ` [Qemu-devel] [PATCH for-2.7 2/2] net: make socket connect non-blocking again Marc-André Lureau
2016-08-23 10:43   ` Cao jin
2016-08-23 13:13     ` Daniel P. Berrange
2016-08-23 13:33       ` Marc-André Lureau
2016-08-30 12:07 ` [Qemu-devel] [PATCH for-2.7 0/2] Fix net socket connect regressions Paolo Bonzini

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.