From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55670) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZHS6E-0005Oh-Gg for qemu-devel@nongnu.org; Tue, 21 Jul 2015 03:36:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZHS69-0005Mq-Db for qemu-devel@nongnu.org; Tue, 21 Jul 2015 03:36:26 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34496) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZHS69-0005MN-7K for qemu-devel@nongnu.org; Tue, 21 Jul 2015 03:36:21 -0400 References: <1437338396-22336-1-git-send-email-pyssling@ludd.ltu.se> From: Paolo Bonzini Message-ID: <55ADF66F.4040809@redhat.com> Date: Tue, 21 Jul 2015 09:36:15 +0200 MIME-Version: 1.0 In-Reply-To: <1437338396-22336-1-git-send-email-pyssling@ludd.ltu.se> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH v4] qemu-char: Fix missed data on unix socket List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: pyssling@ludd.ltu.se, batuzovk@ispras.ru, qemu-devel@nongnu.org On 19/07/2015 22:39, pyssling@ludd.ltu.se wrote: > From: Nils Carlson > > Commit 812c1057 introduced HUP detection on unix and tcp sockets prior > to a read in tcp_chr_read. This unfortunately broke CloudStack 4.2 > which relied on the old behaviour where data on a socket was readable > even if a HUP was present. > > A working solution is to properly check the return values from recv, > handling a closed socket once there is no more data to read. > > Also enable polling for G_IO_NVAL to ensure the callback is called > for all possible events as these should now be possible to handle > with the improved error detection. > > Signed-off-by: Nils Carlson > --- > qemu-char.c | 15 +++++++-------- > 1 file changed, 7 insertions(+), 8 deletions(-) > > diff --git a/qemu-char.c b/qemu-char.c > index 617e034..3cbfe3e 100644 > --- a/qemu-char.c > +++ b/qemu-char.c > @@ -807,7 +807,8 @@ static gboolean io_watch_poll_prepare(GSource *source, gint *timeout_) > } > > if (now_active) { > - iwp->src = g_io_create_watch(iwp->channel, G_IO_IN | G_IO_ERR | G_IO_HUP); > + iwp->src = g_io_create_watch(iwp->channel, > + G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL); > g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL); > g_source_attach(iwp->src, NULL); > } else { > @@ -2847,12 +2848,6 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) > uint8_t buf[READ_BUF_LEN]; > int len, size; > > - if (cond & G_IO_HUP) { > - /* connection closed */ > - tcp_chr_disconnect(chr); > - return TRUE; > - } > - > if (!s->connected || s->max_size <= 0) { > return TRUE; > } > @@ -2860,7 +2855,11 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) > if (len > s->max_size) > len = s->max_size; > size = tcp_chr_recv(chr, (void *)buf, len); > - if (size == 0) { > + if (size == 0 || > + (size < 0 && > + !(errno == EAGAIN || > + errno == EWOULDBLOCK || > + errno == EINTR))) { You need to check socket_error() here instead of errno. Also, EINTR is not a disconnection. However, I can fix these up for you. I'll send a pull request. Paolo > /* connection closed */ > tcp_chr_disconnect(chr); > } else if (size > 0) { >