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