From f399612c56ee81c8dab82811e59bcea242cb7aec Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Thu, 6 Oct 2011 10:41:28 +0100 Subject: [PATCH] Fix deadlock when the RPC program is unknown Commit 597fe3cee68f561a181967b59a87b4e5c5880c4c accidentally introduced a deadlock when reporting an unknown RPC program. The virNetServerDispatchNewMessage method is called with the client locked, and must therefore not attempt to send any RPC messages back to the client. Only once the incoming message is passed off to the virNetServerHandleJob worker is it safe to start sending messages back * src/rpc/virnetserver.c: Delay checking for unknown RPC program until in worker thread --- src/rpc/virnetserver.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c index d71ed18d72..9588077334 100644 --- a/src/rpc/virnetserver.c +++ b/src/rpc/virnetserver.c @@ -133,6 +133,14 @@ static void virNetServerHandleJob(void *jobOpaque, void *opaque) VIR_DEBUG("server=%p client=%p message=%p prog=%p", srv, job->client, job->msg, job->prog); + if (!job->prog) { + if (virNetServerProgramUnknownError(job->client, + job->msg, + &job->msg->header) < 0) + goto error; + goto cleanup; + } + if (virNetServerProgramDispatch(job->prog, srv, job->client, @@ -142,6 +150,8 @@ static void virNetServerHandleJob(void *jobOpaque, void *opaque) virNetServerLock(srv); virNetServerProgramFree(job->prog); virNetServerUnlock(srv); + +cleanup: virNetServerClientFree(job->client); VIR_FREE(job); return; @@ -184,18 +194,14 @@ static int virNetServerDispatchNewMessage(virNetServerClientPtr client, } } - if (!prog) { - virNetServerProgramUnknownError(client, msg, &msg->header); - goto cleanup; + if (prog) { + virNetServerProgramRef(prog); + job->prog = prog; + priority = virNetServerProgramGetPriority(prog, msg->header.proc); } - virNetServerProgramRef(prog); - job->prog = prog; - priority = virNetServerProgramGetPriority(prog, msg->header.proc); - ret = virThreadPoolSendJob(srv->workers, priority, job); -cleanup: if (ret < 0) { VIR_FREE(job); virNetServerProgramFree(prog); -- GitLab