It not done yet. As a result if we doing 'virsh console' and libvirtd is killed we get [1] message as virsh tracks connection status but virsh itself won't exit because it won't get notification that stream is broken. Only after we press a key and virsh tries to write that key code to stream we get an error. So let's add notification that stream's underlying connection is closed. [1] error: Disconnected from qemu:///system due to end of file Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy@xxxxxxxxxxxxx> --- src/rpc/virnetclient.c | 4 ++++ src/rpc/virnetclientstream.c | 30 ++++++++++++++++++++++++++++-- src/rpc/virnetclientstream.h | 2 ++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index 0393587..3fa0320 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -785,6 +785,7 @@ static void virNetClientCloseLocked(virNetClientPtr client) { virKeepAlivePtr ka; + size_t i; VIR_DEBUG("client=%p, sock=%p, reason=%d", client, client->sock, client->closeReason); @@ -825,6 +826,9 @@ virNetClientCloseLocked(virNetClientPtr client) virObjectLock(client); virObjectUnref(client); } + + for (i = 0; i < client->nstreams; i++) + virNetClientStreamSetClientClosed(client->streams[i]); } static void virNetClientCloseInternal(virNetClientPtr client, diff --git a/src/rpc/virnetclientstream.c b/src/rpc/virnetclientstream.c index 834c448..de0c961 100644 --- a/src/rpc/virnetclientstream.c +++ b/src/rpc/virnetclientstream.c @@ -50,6 +50,7 @@ struct _virNetClientStream { virNetMessagePtr rx; bool incomingEOF; virNetClientStreamClosed closed; + bool clientClosed; bool allowSkip; long long holeLength; /* Size of incoming hole in stream. */ @@ -85,7 +86,11 @@ virNetClientStreamEventTimerUpdate(virNetClientStreamPtr st) VIR_DEBUG("Check timer rx=%p cbEvents=%d", st->rx, st->cbEvents); - if (((st->rx || st->incomingEOF || st->err.code != VIR_ERR_OK || st->closed) && + if (((st->rx || + st->incomingEOF || + st->err.code != VIR_ERR_OK || + st->closed || + st->clientClosed) && (st->cbEvents & VIR_STREAM_EVENT_READABLE)) || (st->cbEvents & VIR_STREAM_EVENT_WRITABLE)) { VIR_DEBUG("Enabling event timer"); @@ -107,7 +112,11 @@ virNetClientStreamEventTimer(int timer ATTRIBUTE_UNUSED, void *opaque) if (st->cb && (st->cbEvents & VIR_STREAM_EVENT_READABLE) && - (st->rx || st->incomingEOF || st->err.code != VIR_ERR_OK || st->closed)) + (st->rx || + st->incomingEOF || + st->err.code != VIR_ERR_OK || + st->closed || + st->clientClosed)) events |= VIR_STREAM_EVENT_READABLE; if (st->cb && (st->cbEvents & VIR_STREAM_EVENT_WRITABLE)) @@ -204,6 +213,12 @@ int virNetClientStreamCheckState(virNetClientStreamPtr st) return -1; } + if (st->clientClosed) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("client socket is closed")); + return -1; + } + if (st->closed) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("stream is closed")); @@ -247,6 +262,17 @@ int virNetClientStreamCheckSendStatus(virNetClientStreamPtr st, } +void virNetClientStreamSetClientClosed(virNetClientStreamPtr st) +{ + virObjectLock(st); + + st->clientClosed = true; + virNetClientStreamEventTimerUpdate(st); + + virObjectUnlock(st); +} + + void virNetClientStreamSetClosed(virNetClientStreamPtr st, virNetClientStreamClosed closed) { diff --git a/src/rpc/virnetclientstream.h b/src/rpc/virnetclientstream.h index 33a2af3..f1df4e2 100644 --- a/src/rpc/virnetclientstream.h +++ b/src/rpc/virnetclientstream.h @@ -49,6 +49,8 @@ int virNetClientStreamCheckSendStatus(virNetClientStreamPtr st, int virNetClientStreamSetError(virNetClientStreamPtr st, virNetMessagePtr msg); +void virNetClientStreamSetClientClosed(virNetClientStreamPtr st); + void virNetClientStreamSetClosed(virNetClientStreamPtr st, virNetClientStreamClosed closed); -- 1.8.3.1