From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53643) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WKzsc-0003rH-Sz for qemu-devel@nongnu.org; Tue, 04 Mar 2014 19:40:20 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WKzsV-0000Vk-RC for qemu-devel@nongnu.org; Tue, 04 Mar 2014 19:40:14 -0500 Received: from mail-qa0-x22a.google.com ([2607:f8b0:400d:c00::22a]:56913) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WKzsV-0000VP-Kx for qemu-devel@nongnu.org; Tue, 04 Mar 2014 19:40:07 -0500 Received: by mail-qa0-f42.google.com with SMTP id k15so324641qaq.15 for ; Tue, 04 Mar 2014 16:40:07 -0800 (PST) Sender: Corey Minyard From: minyard@acm.org Date: Tue, 4 Mar 2014 18:38:53 -0600 Message-Id: <1393979937-9082-4-git-send-email-minyard@acm.org> In-Reply-To: <1393979937-9082-1-git-send-email-minyard@acm.org> References: <1393979937-9082-1-git-send-email-minyard@acm.org> Subject: [Qemu-devel] [PATCH 3/7] qemu-char: Wait until socket connect to report connected List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: bcketchum@gmail.com, Corey Minyard , hwd@huawei.com, afaerber@suse.de, mst@redhat.com From: Corey Minyard The socket code was reporting that a socket connection was connected as soon as the connect call was issued. If the connection failed, it would then report it was not connected. With the reconnect code, it's better to wait until the connection is actually operational before reporting that the socket is connected. Signed-off-by: Corey Minyard --- qemu-char.c | 49 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index d9838aa..6d6dd36 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2310,9 +2310,10 @@ static CharDriverState *qemu_chr_open_udp(CharDriverState *chr, QemuOpts *opts) typedef struct { GIOChannel *chan, *listen_chan; + int waitsrc; guint listen_tag; int fd, listen_fd; - int connected; + enum { TCP_NOT_CONNECTED, TCP_WAITING_CONNECT, TCP_CONNECTED } state; int max_size; int do_telnetopt; int do_nodelay; @@ -2325,7 +2326,7 @@ static gboolean tcp_chr_accept(GIOChannel *chan, GIOCondition cond, void *opaque static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) { TCPCharDriver *s = chr->opaque; - if (s->connected) { + if (s->state == TCP_CONNECTED) { return io_channel_send(s->chan, buf, len); } else { /* XXX: indicate an error ? */ @@ -2337,7 +2338,7 @@ static int tcp_chr_read_poll(void *opaque) { CharDriverState *chr = opaque; TCPCharDriver *s = chr->opaque; - if (!s->connected) + if (s->state != TCP_CONNECTED) return 0; s->max_size = qemu_chr_be_can_write(chr); return s->max_size; @@ -2482,7 +2483,7 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) uint8_t buf[READ_BUF_LEN]; int len, size; - if (!s->connected || s->max_size <= 0) { + if (s->state != TCP_CONNECTED || s->max_size <= 0) { return TRUE; } len = sizeof(buf); @@ -2491,7 +2492,7 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) size = tcp_chr_recv(chr, (void *)buf, len); if (size == 0) { /* connection closed */ - s->connected = 0; + s->state = TCP_NOT_CONNECTED; if (s->listen_chan) { s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN, tcp_chr_accept, chr); } @@ -2518,17 +2519,48 @@ CharDriverState *qemu_chr_open_eventfd(CharDriverState *chr, int eventfd) } #endif -static void tcp_chr_connect(void *opaque) +static gboolean tcp_wait_connect(GIOChannel *source, + GIOCondition condition, + gpointer opaque) { CharDriverState *chr = opaque; TCPCharDriver *s = chr->opaque; - s->connected = 1; + if (s->state != TCP_WAITING_CONNECT) { + return FALSE; + } + if (condition & G_IO_ERR || condition & G_IO_HUP) { + /* The connected failed */ + s->state = TCP_NOT_CONNECTED; + g_io_channel_unref(s->chan); + s->chan = NULL; + closesocket(s->fd); + s->fd = -1; + return FALSE; + } + + s->state = TCP_CONNECTED; if (s->chan) { chr->fd_in_tag = io_add_watch_poll(s->chan, tcp_chr_read_poll, tcp_chr_read, chr); } qemu_chr_be_generic_open(chr); + return FALSE; +} + +static void tcp_chr_connect(void *opaque) +{ + CharDriverState *chr = opaque; + TCPCharDriver *s = chr->opaque; + + s->state = TCP_WAITING_CONNECT; + if (s->chan) { + /* Wait until write becomes ready before reporting connected. */ + s->waitsrc = g_io_add_watch(s->chan, + G_IO_OUT | G_IO_HUP | G_IO_ERR, + tcp_wait_connect, + chr); + } } #define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c; @@ -2650,7 +2682,7 @@ static CharDriverState *qemu_chr_open_socket_fd(CharDriverState *chr, s = g_malloc0(sizeof(TCPCharDriver)); - s->connected = 0; + s->state = TCP_NOT_CONNECTED; s->fd = -1; s->listen_fd = -1; s->msgfd = -1; @@ -2695,7 +2727,6 @@ static CharDriverState *qemu_chr_open_socket_fd(CharDriverState *chr, s->do_telnetopt = 1; } } else { - s->connected = 1; s->fd = fd; socket_set_nodelay(fd); s->chan = io_channel_from_socket(s->fd); -- 1.8.3.1