From c91776d5ff9c99dbb711a7f21ecd526984f1806c Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Fri, 11 Sep 2015 17:07:56 +0200 Subject: [PATCH] client rpc: Report proper error for keepalive disconnections Whenever a connection was closed due to keepalive timeout, we would log a warning but the interrupted API would return rather useless generic error: internal error: received hangup / error event on socket Let's report a proper keepalive timeout error and make sure it is propagated to all pending APIs. The error should be better now: internal error: connection closed due to keepalive timeout Based on an old patch from Martin Kletzander. Signed-off-by: Jiri Denemark --- src/rpc/virkeepalive.c | 10 +++++----- src/rpc/virnetclient.c | 12 ++++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/rpc/virkeepalive.c b/src/rpc/virkeepalive.c index c882313339..c9faf88590 100644 --- a/src/rpc/virkeepalive.c +++ b/src/rpc/virkeepalive.c @@ -136,11 +136,11 @@ virKeepAliveTimerInternal(virKeepAlivePtr ka, ka, ka->client, ka->countToDeath, timeval); if (ka->countToDeath == 0) { - VIR_WARN("No response from client %p after %d keepalive messages in" - " %d seconds", - ka->client, - ka->count, - timeval); + VIR_DEBUG("No response from client %p after %d keepalive messages " + "in %d seconds", + ka->client, ka->count, timeval); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("connection closed due to keepalive timeout")); return true; } else { ka->countToDeath--; diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index d0b96b654f..6e59ea6f24 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -107,6 +107,7 @@ struct _virNetClient { virKeepAlivePtr keepalive; bool wantClose; int closeReason; + virErrorPtr error; virNetClientCloseFunc closeCb; void *closeOpaque; @@ -636,10 +637,14 @@ virNetClientMarkClose(virNetClientPtr client, int reason) { VIR_DEBUG("client=%p, reason=%d", client, reason); + if (client->sock) virNetSocketRemoveIOCallback(client->sock); + /* Don't override reason that's already set. */ if (!client->wantClose) { + if (!client->error) + client->error = virSaveLastError(); client->wantClose = true; client->closeReason = reason; } @@ -670,6 +675,9 @@ virNetClientCloseLocked(virNetClientPtr client) client->keepalive = NULL; client->wantClose = false; + virFreeError(client->error); + client->error = NULL; + if (ka || client->closeCb) { virNetClientCloseFunc closeCb = client->closeCb; void *closeOpaque = client->closeOpaque; @@ -1602,6 +1610,10 @@ static int virNetClientIOEventLoop(virNetClientPtr client, } error: + if (client->error) { + VIR_DEBUG("error on socket: %s", client->error->message); + virSetError(client->error); + } virNetClientCallRemove(&client->waitDispatch, thiscall); virNetClientIOEventLoopPassTheBuck(client, thiscall); return -1; -- GitLab