From 3cfdc57b8553cae95b8849bbcb7a4b227085cec1 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 8 Jul 2011 12:54:29 +0100 Subject: [PATCH] Fix sending of reply to final RPC message The dispatch for the CLOSE RPC call was invoking the method virNetServerClientClose(). This caused the client connection to be immediately terminated. This meant the reply to the final RPC message was never sent. Prior to the RPC rewrite we merely flagged the connection for closing, and actually closed it when the next RPC call dispatch had completed. * daemon/remote.c: Flag connection for a delayed close * daemon/stream.c: Update to use new API for closing failed connection * src/rpc/virnetserverclient.c, src/rpc/virnetserverclient.h: Add support for a delayed connection close. Rename the virNetServerClientMarkClose method to virNetServerClientImmediateClose to clarify its semantics --- daemon/remote.c | 4 ++-- daemon/stream.c | 6 +++--- src/rpc/virnetserverclient.c | 13 ++++++++++++- src/rpc/virnetserverclient.h | 5 +++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 288990855e..a2e79efa99 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -483,11 +483,11 @@ cleanup: static int remoteDispatchClose(virNetServerPtr server ATTRIBUTE_UNUSED, - virNetServerClientPtr client, + virNetServerClientPtr client ATTRIBUTE_UNUSED, virNetMessageHeaderPtr hdr ATTRIBUTE_UNUSED, virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED) { - virNetServerClientClose(client); + virNetServerClientDelayedClose(client); return 0; } diff --git a/daemon/stream.c b/daemon/stream.c index 28f6c326d7..4a8f1eed91 100644 --- a/daemon/stream.c +++ b/daemon/stream.c @@ -338,7 +338,7 @@ int daemonFreeClientStream(virNetServerClientPtr client, memset(msg, 0, sizeof(*msg)); msg->header.type = VIR_NET_REPLY; if (virNetServerClientSendMessage(client, msg) < 0) { - virNetServerClientMarkClose(client); + virNetServerClientImmediateClose(client); virNetMessageFree(msg); ret = -1; } @@ -608,7 +608,7 @@ daemonStreamHandleWrite(virNetServerClientPtr client, virNetMessageQueueServe(&stream->rx); if (ret < 0) { virNetMessageFree(msg); - virNetServerClientMarkClose(client); + virNetServerClientImmediateClose(client); return -1; } @@ -623,7 +623,7 @@ daemonStreamHandleWrite(virNetServerClientPtr client, msg->header.type = VIR_NET_REPLY; if (virNetServerClientSendMessage(client, msg) < 0) { virNetMessageFree(msg); - virNetServerClientMarkClose(client); + virNetServerClientImmediateClose(client); return -1; } } diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c index 6aeb3a4d4a..742c3a4bba 100644 --- a/src/rpc/virnetserverclient.c +++ b/src/rpc/virnetserverclient.c @@ -61,6 +61,7 @@ struct _virNetServerClient { int refs; bool wantClose; + bool delayedClose; virMutex lock; virNetSocketPtr sock; int auth; @@ -587,7 +588,14 @@ bool virNetServerClientIsClosed(virNetServerClientPtr client) return closed; } -void virNetServerClientMarkClose(virNetServerClientPtr client) +void virNetServerClientDelayedClose(virNetServerClientPtr client) +{ + virNetServerClientLock(client); + client->delayedClose = true; + virNetServerClientUnlock(client); +} + +void virNetServerClientImmediateClose(virNetServerClientPtr client) { virNetServerClientLock(client); client->wantClose = true; @@ -852,6 +860,9 @@ virNetServerClientDispatchWrite(virNetServerClientPtr client) virNetMessageFree(msg); virNetServerClientUpdateEvent(client); + + if (client->delayedClose) + client->wantClose = true; } } } diff --git a/src/rpc/virnetserverclient.h b/src/rpc/virnetserverclient.h index 66510c31c5..3d2e1fba45 100644 --- a/src/rpc/virnetserverclient.h +++ b/src/rpc/virnetserverclient.h @@ -86,9 +86,10 @@ void virNetServerClientSetDispatcher(virNetServerClientPtr client, virNetServerClientDispatchFunc func, void *opaque); void virNetServerClientClose(virNetServerClientPtr client); - bool virNetServerClientIsClosed(virNetServerClientPtr client); -void virNetServerClientMarkClose(virNetServerClientPtr client); + +void virNetServerClientDelayedClose(virNetServerClientPtr client); +void virNetServerClientImmediateClose(virNetServerClientPtr client); bool virNetServerClientWantClose(virNetServerClientPtr client); int virNetServerClientInit(virNetServerClientPtr client);