rpc: Correct locking and simplify the function

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. The same applies to the tracking of
authentications.

Signed-off-by: Marc Hartmayer <mhartmay@linux.vnet.ibm.com>
This commit is contained in:
Marc Hartmayer 2017-12-21 15:29:03 +01:00 committed by John Ferlan
parent be680bed4a
commit 0eaa59dce1
4 changed files with 38 additions and 27 deletions

View File

@ -125,6 +125,7 @@ virNetServerUpdateServices;
# rpc/virnetserverclient.h # rpc/virnetserverclient.h
virNetServerClientAddFilter; virNetServerClientAddFilter;
virNetServerClientClose; virNetServerClientClose;
virNetServerClientCloseLocked;
virNetServerClientDelayedClose; virNetServerClientDelayedClose;
virNetServerClientGetAuth; virNetServerClientGetAuth;
virNetServerClientGetFD; virNetServerClientGetFD;
@ -138,7 +139,7 @@ virNetServerClientGetUNIXIdentity;
virNetServerClientImmediateClose; virNetServerClientImmediateClose;
virNetServerClientInit; virNetServerClientInit;
virNetServerClientInitKeepAlive; virNetServerClientInitKeepAlive;
virNetServerClientIsClosed; virNetServerClientIsClosedLocked;
virNetServerClientIsLocal; virNetServerClientIsLocal;
virNetServerClientIsSecure; virNetServerClientIsSecure;
virNetServerClientLocalAddrStringSASL; virNetServerClientLocalAddrStringSASL;
@ -156,7 +157,7 @@ virNetServerClientSetCloseHook;
virNetServerClientSetDispatcher; virNetServerClientSetDispatcher;
virNetServerClientSetReadonly; virNetServerClientSetReadonly;
virNetServerClientStartKeepAlive; virNetServerClientStartKeepAlive;
virNetServerClientWantClose; virNetServerClientWantCloseLocked;
# rpc/virnetservermdns.h # rpc/virnetservermdns.h

View File

@ -285,8 +285,10 @@ int virNetServerAddClient(virNetServerPtr srv,
goto error; goto error;
srv->clients[srv->nclients-1] = virObjectRef(client); srv->clients[srv->nclients-1] = virObjectRef(client);
if (virNetServerClientNeedAuth(client)) virObjectLock(client);
if (virNetServerClientNeedAuthLocked(client))
virNetServerTrackPendingAuthLocked(srv); virNetServerTrackPendingAuthLocked(srv);
virObjectUnlock(client);
virNetServerCheckLimits(srv); virNetServerCheckLimits(srv);
@ -847,6 +849,7 @@ void
virNetServerProcessClients(virNetServerPtr srv) virNetServerProcessClients(virNetServerPtr srv)
{ {
size_t i; size_t i;
virNetServerClientPtr client;
virObjectLock(srv); virObjectLock(srv);
@ -855,15 +858,18 @@ virNetServerProcessClients(virNetServerPtr srv)
/* Coverity 5.3.0 couldn't see that srv->clients is non-NULL /* Coverity 5.3.0 couldn't see that srv->clients is non-NULL
* if srv->nclients is non-zero. */ * if srv->nclients is non-zero. */
sa_assert(srv->clients); 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);
if (virNetServerClientIsClosedLocked(client)) {
VIR_DELETE_ELEMENT(srv->clients, i, srv->nclients); VIR_DELETE_ELEMENT(srv->clients, i, srv->nclients);
if (virNetServerClientNeedAuth(client)) if (virNetServerClientNeedAuthLocked(client))
virNetServerTrackCompletedAuthLocked(srv); virNetServerTrackCompletedAuthLocked(srv);
virObjectUnlock(client);
virNetServerCheckLimits(srv); virNetServerCheckLimits(srv);
@ -872,6 +878,8 @@ virNetServerProcessClients(virNetServerPtr srv)
virObjectLock(srv); virObjectLock(srv);
goto reprocess; goto reprocess;
} else {
virObjectUnlock(client);
} }
} }

View File

@ -987,17 +987,15 @@ void virNetServerClientDispose(void *obj)
* Full free of the client is done later in a safe point * Full free of the client is done later in a safe point
* where it can be guaranteed it is no longer in use * where it can be guaranteed it is no longer in use
*/ */
void virNetServerClientClose(virNetServerClientPtr client) void
virNetServerClientCloseLocked(virNetServerClientPtr client)
{ {
virNetServerClientCloseFunc cf; virNetServerClientCloseFunc cf;
virKeepAlivePtr ka; virKeepAlivePtr ka;
virObjectLock(client);
VIR_DEBUG("client=%p", client); VIR_DEBUG("client=%p", client);
if (!client->sock) { if (!client->sock)
virObjectUnlock(client);
return; return;
}
if (client->keepalive) { if (client->keepalive) {
virKeepAliveStop(client->keepalive); virKeepAliveStop(client->keepalive);
@ -1048,20 +1046,25 @@ void virNetServerClientClose(virNetServerClientPtr client)
virObjectUnref(client->sock); virObjectUnref(client->sock);
client->sock = NULL; client->sock = NULL;
} }
virObjectUnlock(client);
} }
bool virNetServerClientIsClosed(virNetServerClientPtr client) void
virNetServerClientClose(virNetServerClientPtr client)
{ {
bool closed;
virObjectLock(client); virObjectLock(client);
closed = client->sock == NULL ? true : false; virNetServerClientCloseLocked(client);
virObjectUnlock(client); virObjectUnlock(client);
return closed;
} }
bool
virNetServerClientIsClosedLocked(virNetServerClientPtr client)
{
return client->sock == NULL ? true : false;
}
void virNetServerClientDelayedClose(virNetServerClientPtr client) void virNetServerClientDelayedClose(virNetServerClientPtr client)
{ {
virObjectLock(client); virObjectLock(client);
@ -1076,13 +1079,11 @@ void virNetServerClientImmediateClose(virNetServerClientPtr client)
virObjectUnlock(client); virObjectUnlock(client);
} }
bool virNetServerClientWantClose(virNetServerClientPtr client)
bool
virNetServerClientWantCloseLocked(virNetServerClientPtr client)
{ {
bool wantClose; return client->wantClose;
virObjectLock(client);
wantClose = client->wantClose;
virObjectUnlock(client);
return wantClose;
} }

View File

@ -124,11 +124,12 @@ void virNetServerClientSetDispatcher(virNetServerClientPtr client,
virNetServerClientDispatchFunc func, virNetServerClientDispatchFunc func,
void *opaque); void *opaque);
void virNetServerClientClose(virNetServerClientPtr client); void virNetServerClientClose(virNetServerClientPtr client);
bool virNetServerClientIsClosed(virNetServerClientPtr client); void virNetServerClientCloseLocked(virNetServerClientPtr client);
bool virNetServerClientIsClosedLocked(virNetServerClientPtr client);
void virNetServerClientDelayedClose(virNetServerClientPtr client); void virNetServerClientDelayedClose(virNetServerClientPtr client);
void virNetServerClientImmediateClose(virNetServerClientPtr client); void virNetServerClientImmediateClose(virNetServerClientPtr client);
bool virNetServerClientWantClose(virNetServerClientPtr client); bool virNetServerClientWantCloseLocked(virNetServerClientPtr client);
int virNetServerClientInit(virNetServerClientPtr client); int virNetServerClientInit(virNetServerClientPtr client);