]> xenbits.xensource.com Git - libvirt.git/commitdiff
Fix deadlock when the RPC program is unknown
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 6 Oct 2011 09:41:28 +0000 (10:41 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 7 Oct 2011 15:53:30 +0000 (16:53 +0100)
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

index d71ed18d729771306c97eb45f5eab71ac613014f..95880773347c716311fe5edbca923feb629ac296 100644 (file)
@@ -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);