* [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.