[libvirt] [PATCH v3 04/13] virsh: Always run event loop

Jiri Denemark jdenemar at redhat.com
Wed Oct 12 05:16:22 UTC 2011


Since virsh already implements event loop, it has to also run it. So far
the event loop was only running during virsh console command.
---
Notes:
    Version 3:
    - new patch

 tools/console.c |   17 ++++++++++++++---
 tools/virsh.c   |   31 +++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/tools/console.c b/tools/console.c
index 0f85bc7..e9e01a4 100644
--- a/tools/console.c
+++ b/tools/console.c
@@ -41,6 +41,7 @@
 # include "util.h"
 # include "virfile.h"
 # include "memory.h"
+# include "threads.h"
 # include "virterror_internal.h"
 
 
@@ -60,6 +61,8 @@ typedef virConsole *virConsolePtr;
 struct virConsole {
     virStreamPtr st;
     bool quit;
+    virMutex lock;
+    virCond cond;
 
     int stdinWatch;
     int stdoutWatch;
@@ -89,7 +92,6 @@ cfmakeraw (struct termios *attr)
 static void
 virConsoleShutdown(virConsolePtr con)
 {
-    con->quit = true;
     if (con->st) {
         virStreamEventRemoveCallback(con->st);
         virStreamAbort(con->st);
@@ -101,6 +103,8 @@ virConsoleShutdown(virConsolePtr con)
         virEventRemoveHandle(con->stdoutWatch);
     con->stdinWatch = -1;
     con->stdoutWatch = -1;
+    con->quit = true;
+    virCondSignal(&con->cond);
 }
 
 static void
@@ -334,6 +338,9 @@ int vshRunConsole(virDomainPtr dom, const char *dev_name)
     if (virDomainOpenConsole(dom, dev_name, con->st, 0) < 0)
         goto cleanup;
 
+    if (virCondInit(&con->cond) < 0 || virMutexInit(&con->lock) < 0)
+        goto cleanup;
+
     con->stdinWatch = virEventAddHandle(STDIN_FILENO,
                                         VIR_EVENT_HANDLE_READABLE,
                                         virConsoleEventOnStdin,
@@ -352,8 +359,10 @@ int vshRunConsole(virDomainPtr dom, const char *dev_name)
                               NULL);
 
     while (!con->quit) {
-        if (virEventRunDefaultImpl() < 0)
-            break;
+        if (virCondWait(&con->cond, &con->lock) < 0) {
+            VIR_ERROR(_("unable to wait on console condition"));
+            goto cleanup;
+        }
     }
 
     ret = 0;
@@ -363,6 +372,8 @@ int vshRunConsole(virDomainPtr dom, const char *dev_name)
     if (con) {
         if (con->st)
             virStreamFree(con->st);
+        virMutexDestroy(&con->lock);
+        ignore_value(virCondDestroy(&con->cond));
         VIR_FREE(con);
     }
 
diff --git a/tools/virsh.c b/tools/virsh.c
index bcf0603..1434697 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -248,6 +248,9 @@ typedef struct __vshControl {
                                    virDomainGetState is not supported */
     bool useSnapshotOld;        /* cannot use virDomainSnapshotGetParent or
                                    virDomainSnapshotNumChildren */
+    virThread eventLoop;
+    bool eventLoopStarted;
+    bool quit;
 } __vshControl;
 
 typedef struct vshCmdGrp {
@@ -15843,6 +15846,19 @@ vshError(vshControl *ctl, const char *format, ...)
 }
 
 
+static void
+vshEventLoop(void *opaque)
+{
+    vshControl *ctl = opaque;
+
+    while (!ctl->quit) {
+        if (virEventRunDefaultImpl() < 0) {
+            virshReportError(ctl);
+        }
+    }
+}
+
+
 /*
  * Initialize connection.
  */
@@ -15888,6 +15904,10 @@ vshInit(vshControl *ctl)
     if (virEventRegisterDefaultImpl() < 0)
         return false;
 
+    if (virThreadCreate(&ctl->eventLoop, true, vshEventLoop, ctl) < 0)
+        return false;
+    ctl->eventLoopStarted = true;
+
     if (ctl->name) {
         ctl->conn = virConnectOpenAuth(ctl->name,
                                        virConnectAuthPtrDefault,
@@ -16276,6 +16296,7 @@ vshReadline (vshControl *ctl, const char *prompt)
 static bool
 vshDeinit(vshControl *ctl)
 {
+    ctl->quit = true;
     vshReadlineDeinit(ctl);
     vshCloseLogFile(ctl);
     VIR_FREE(ctl->name);
@@ -16287,6 +16308,16 @@ vshDeinit(vshControl *ctl)
     }
     virResetLastError();
 
+    if (ctl->eventLoopStarted) {
+        /* HACK: Add a dummy timeout to break event loop */
+        int timer = virEventAddTimeout(-1, NULL, NULL, NULL);
+        if (timer != -1)
+            virEventRemoveTimeout(timer);
+
+        virThreadJoin(&ctl->eventLoop);
+        ctl->eventLoopStarted = false;
+    }
+
     return true;
 }
 
-- 
1.7.7




More information about the libvir-list mailing list