From 43b7292293424187b7c22e36d5502be78a20e109 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 7 Oct 2011 17:38:59 +0100 Subject: [PATCH] Fix handling of stream EOF Very occasionally the sequence of events from poll would result in getting a HANGUP on its own, instead of a HANGUP+READABLE at the same time. In the former case we would send back an error event to the client, but never send the empty packet to indicate EOF. (cherry picked from commit 1d46b2e900498a3f389fcbb89fc7b27d22f36d4a) --- daemon/stream.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/daemon/stream.c b/daemon/stream.c index e3214c2f57..2940204141 100644 --- a/daemon/stream.c +++ b/daemon/stream.c @@ -143,7 +143,8 @@ daemonStreamEvent(virStreamPtr st, int events, void *opaque) VIR_DEBUG("st=%p events=%d EOF=%d closed=%d", st, events, stream->recvEOF, stream->closed); - if (events & VIR_STREAM_EVENT_WRITABLE) { + if (!stream->closed && + (events & VIR_STREAM_EVENT_WRITABLE)) { if (daemonStreamHandleWrite(client, stream) < 0) { daemonRemoveClientStream(client, stream); virNetServerClientClose(client); @@ -151,9 +152,9 @@ daemonStreamEvent(virStreamPtr st, int events, void *opaque) } } - if (!stream->recvEOF && - (events & (VIR_STREAM_EVENT_READABLE | VIR_STREAM_EVENT_HANGUP))) { - events = events & ~(VIR_STREAM_EVENT_READABLE | VIR_STREAM_EVENT_HANGUP); + if (!stream->closed && !stream->recvEOF && + (events & (VIR_STREAM_EVENT_READABLE))) { + events = events & ~(VIR_STREAM_EVENT_READABLE); if (daemonStreamHandleRead(client, stream) < 0) { daemonRemoveClientStream(client, stream); virNetServerClientClose(client); @@ -190,6 +191,37 @@ daemonStreamEvent(virStreamPtr st, int events, void *opaque) } } + + /* If we got HANGUP, we need to only send an empty + * packet so the client sees an EOF and cleans up + */ + if (!stream->closed && !stream->recvEOF && + (events & VIR_STREAM_EVENT_HANGUP)) { + virNetMessagePtr msg; + events &= ~(VIR_STREAM_EVENT_HANGUP); + stream->tx = 0; + stream->recvEOF = 1; + if (!(msg = virNetMessageNew(false))) { + daemonRemoveClientStream(client, stream); + virNetServerClientClose(client); + goto cleanup; + } + msg->cb = daemonStreamMessageFinished; + msg->opaque = stream; + stream->refs++; + if (virNetServerProgramSendStreamData(remoteProgram, + client, + msg, + stream->procedure, + stream->serial, + "", 0) < 0) { + virNetMessageFree(msg); + daemonRemoveClientStream(client, stream); + virNetServerClientClose(client); + goto cleanup; + } + } + if (!stream->closed && (events & (VIR_STREAM_EVENT_ERROR | VIR_STREAM_EVENT_HANGUP))) { int ret; -- 2.47.3