The lock for @client must not only be held for the duration of
checking whether the client wants to close, but also for as long as
we're closing the client.
Signed-off-by: Marc Hartmayer <mhartmay(a)linux.vnet.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy(a)linux.vnet.ibm.com>
Reviewed-by: Stefan Zimmermann <stzi(a)linux.vnet.ibm.com>
---
src/libvirt_remote.syms | 3 ++-
src/rpc/virnetserver.c | 12 ++++++++----
src/rpc/virnetserverclient.c | 25 ++++++++++++++-----------
src/rpc/virnetserverclient.h | 3 ++-
4 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/src/libvirt_remote.syms b/src/libvirt_remote.syms
index 61c20d530bc8..3ce5694b781d 100644
--- a/src/libvirt_remote.syms
+++ b/src/libvirt_remote.syms
@@ -125,6 +125,7 @@ virNetServerUpdateServices;
# rpc/virnetserverclient.h
virNetServerClientAddFilter;
virNetServerClientClose;
+virNetServerClientCloseLocked;
virNetServerClientDelayedClose;
virNetServerClientGetAuth;
virNetServerClientGetFD;
@@ -154,7 +155,7 @@ virNetServerClientSetAuth;
virNetServerClientSetCloseHook;
virNetServerClientSetDispatcher;
virNetServerClientStartKeepAlive;
-virNetServerClientWantClose;
+virNetServerClientWantCloseLocked;
# rpc/virnetservermdns.h
diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
index 2b76daab5566..dde9b73fc250 100644
--- a/src/rpc/virnetserver.c
+++ b/src/rpc/virnetserver.c
@@ -846,6 +846,7 @@ void
virNetServerProcessClients(virNetServerPtr srv)
{
size_t i;
+ virNetServerClientPtr client;
virObjectLock(srv);
@@ -854,11 +855,14 @@ virNetServerProcessClients(virNetServerPtr srv)
/* Coverity 5.3.0 couldn't see that srv->clients is non-NULL
* if srv->nclients is non-zero. */
sa_assert(srv->clients);
- if (virNetServerClientWantClose(srv->clients[i]))
- virNetServerClientClose(srv->clients[i]);
- if (virNetServerClientIsClosed(srv->clients[i])) {
- virNetServerClientPtr client = srv->clients[i];
+ client = srv->clients[i];
+ virObjectLock(client);
+ if (virNetServerClientWantCloseLocked(client))
+ virNetServerClientCloseLocked(client);
+ virObjectUnlock(client);
+
+ if (virNetServerClientIsClosed(client)) {
VIR_DELETE_ELEMENT(srv->clients, i, srv->nclients);
if (virNetServerClientNeedAuth(client))
diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
index 0ee299e2d6ec..96fd1e6d15c2 100644
--- a/src/rpc/virnetserverclient.c
+++ b/src/rpc/virnetserverclient.c
@@ -962,17 +962,15 @@ void virNetServerClientDispose(void *obj)
* Full free of the client is done later in a safe point
* where it can be guaranteed it is no longer in use
*/
-void virNetServerClientClose(virNetServerClientPtr client)
+void
+virNetServerClientCloseLocked(virNetServerClientPtr client)
{
virNetServerClientCloseFunc cf;
virKeepAlivePtr ka;
- virObjectLock(client);
VIR_DEBUG("client=%p", client);
- if (!client->sock) {
- virObjectUnlock(client);
+ if (!client->sock)
return;
- }
if (client->keepalive) {
virKeepAliveStop(client->keepalive);
@@ -1023,7 +1021,14 @@ void virNetServerClientClose(virNetServerClientPtr client)
virObjectUnref(client->sock);
client->sock = NULL;
}
+}
+
+void
+virNetServerClientClose(virNetServerClientPtr client)
+{
+ virObjectLock(client);
+ virNetServerClientCloseLocked(client);
virObjectUnlock(client);
}
@@ -1051,13 +1056,11 @@ void virNetServerClientImmediateClose(virNetServerClientPtr
client)
virObjectUnlock(client);
}
-bool virNetServerClientWantClose(virNetServerClientPtr client)
+
+/* @client needs to be locked by the caller */
+bool virNetServerClientWantCloseLocked(virNetServerClientPtr client)
{
- bool wantClose;
- virObjectLock(client);
- wantClose = client->wantClose;
- virObjectUnlock(client);
- return wantClose;
+ return client->wantClose;
}
diff --git a/src/rpc/virnetserverclient.h b/src/rpc/virnetserverclient.h
index e45c78882ef7..60ad0f9ed326 100644
--- a/src/rpc/virnetserverclient.h
+++ b/src/rpc/virnetserverclient.h
@@ -123,11 +123,12 @@ void virNetServerClientSetDispatcher(virNetServerClientPtr client,
virNetServerClientDispatchFunc func,
void *opaque);
void virNetServerClientClose(virNetServerClientPtr client);
+void virNetServerClientCloseLocked(virNetServerClientPtr client);
bool virNetServerClientIsClosed(virNetServerClientPtr client);
void virNetServerClientDelayedClose(virNetServerClientPtr client);
void virNetServerClientImmediateClose(virNetServerClientPtr client);
-bool virNetServerClientWantClose(virNetServerClientPtr client);
+bool virNetServerClientWantCloseLocked(virNetServerClientPtr client);
int virNetServerClientInit(virNetServerClientPtr client);
--
2.13.4