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(a)virtuozzo.com>
---
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