[libvirt] [PATCH 2/2] Cancel migration/dump if user presses Ctrl-C when migration/dump is in progress

Hu Tao hutao at cn.fujitsu.com
Thu Dec 23 09:07:34 UTC 2010


---
 src/remote/remote_driver.c |    2 +-
 tools/virsh.c              |  126 ++++++++++++++++++++++++++++++++++++++------
 2 files changed, 110 insertions(+), 18 deletions(-)

diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index ee2de4a..d24d54f 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -10122,7 +10122,7 @@ remoteIOEventLoop(virConnectPtr conn,
 
     repoll:
         ret = poll(fds, ARRAY_CARDINALITY(fds), -1);
-        if (ret < 0 && errno == EAGAIN)
+        if (ret < 0 && (errno == EAGAIN || errno == EINTR))
             goto repoll;
 
 #ifdef HAVE_PTHREAD_SIGMASK
diff --git a/tools/virsh.c b/tools/virsh.c
index 8c123bb..efc7d1a 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -54,6 +54,9 @@
 #include "files.h"
 #include "../daemon/event.h"
 #include "configmake.h"
+#include "threads.h"
+#include "threadpool.h"
+#include "datatypes.h"
 
 static char *progname;
 
@@ -208,6 +211,7 @@ typedef struct __vshCmd {
 typedef struct __vshControl {
     char *name;                 /* connection name */
     virConnectPtr conn;         /* connection to hypervisor (MAY BE NULL) */
+    virDomainPtr dom;
     vshCmd *cmd;                /* the current command */
     char *cmdstr;               /* string with command */
     int imode;                  /* interactive mode? */
@@ -221,6 +225,9 @@ typedef struct __vshControl {
     int log_fd;                 /* log file descriptor */
     char *historydir;           /* readline history directory name */
     char *historyfile;          /* readline history file name */
+
+    virMutex mutex;
+    virThreadPoolPtr threadPool;
 } __vshControl;
 
 typedef struct vshCmdGrp {
@@ -229,6 +236,7 @@ typedef struct vshCmdGrp {
     const vshCmdDef *commands;
 } vshCmdGrp;
 
+static vshControl _ctl;
 static const vshCmdGrp cmdGroups[];
 
 static void vshError(vshControl *ctl, const char *format, ...)
@@ -258,6 +266,7 @@ static long long vshCommandOptLongLong(const vshCmd *cmd, const char *name,
                                        int *found);
 static int vshCommandOptBool(const vshCmd *cmd, const char *name);
 static char *vshCommandOptArgv(const vshCmd *cmd, int count);
+static int vshCommandStringParse(vshControl *ctl, char *cmdstr);
 
 #define VSH_BYID     (1 << 1)
 #define VSH_BYUUID   (1 << 2)
@@ -509,6 +518,44 @@ static void vshCatchDisconnect(int sig, siginfo_t * siginfo,
     if ((sig == SIGPIPE) || (siginfo->si_signo == SIGPIPE))
         disconnected++;
 }
+#endif
+
+#ifdef SIGINT
+static void vshCatchInt(int sig, siginfo_t *siginfo,
+                        void *context ATTRIBUTE_UNUSED) {
+    vshControl *ctl = &_ctl;
+    vshCmd *cmds, *c;
+    char *cmdStr = NULL;
+
+    virMutexLock(&ctl->mutex);
+    if (!ctl->dom)
+        goto error;
+
+    if (virAsprintf(&cmdStr, "domjobabort %s", ctl->dom->name) < 0)
+        goto error;
+
+    if ((sig == SIGINT) || (siginfo->si_signo == SIGINT)) {
+        if (!vshConnectionUsability (ctl, ctl->conn))
+            goto error;
+
+        vshCommandStringParse(ctl, cmdStr);
+        cmds = ctl->cmd;
+        ctl->cmd = NULL;
+        virMutexUnlock(&ctl->mutex);
+        do {
+            c = cmds;
+            cmds = cmds->next;
+            c->next = NULL;
+            ignore_value(virThreadPoolSendJob(ctl->threadPool, c, true));
+        } while (cmds);
+    }
+    VIR_FREE(cmdStr);
+    return;
+error:
+    virMutexUnlock(&ctl->mutex);
+    VIR_FREE(cmdStr);
+}
+#endif
 
 /*
  * vshSetupSignals:
@@ -520,17 +567,20 @@ static void
 vshSetupSignals(void) {
     struct sigaction sig_action;
 
-    sig_action.sa_sigaction = vshCatchDisconnect;
     sig_action.sa_flags = SA_SIGINFO;
     sigemptyset(&sig_action.sa_mask);
 
+#ifdef SIGPIPE
+    sig_action.sa_sigaction = vshCatchDisconnect;
     sigaction(SIGPIPE, &sig_action, NULL);
-}
-#else
-static void
-vshSetupSignals(void) {}
 #endif
 
+#ifdef SIGINT
+    sig_action.sa_sigaction = vshCatchInt;
+    sigaction(SIGINT, &sig_action, NULL);
+#endif
+}
+
 /*
  * vshReconnect:
  *
@@ -1848,6 +1898,10 @@ cmdDump(vshControl *ctl, const vshCmd *cmd)
     if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
         return FALSE;
 
+    virMutexLock(&ctl->mutex);
+    ctl->dom = dom;
+    virMutexUnlock(&ctl->mutex);
+
     if (vshCommandOptBool (cmd, "live"))
         flags |= VIR_DUMP_LIVE;
     if (vshCommandOptBool (cmd, "crash"))
@@ -1860,6 +1914,9 @@ cmdDump(vshControl *ctl, const vshCmd *cmd)
         ret = FALSE;
     }
 
+    virMutexLock(&ctl->mutex);
+    ctl->dom = NULL;
+    virMutexUnlock(&ctl->mutex);
     virDomainFree(dom);
     return ret;
 }
@@ -3396,6 +3453,9 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd)
     if (!(dom = vshCommandOptDomain (ctl, cmd, NULL)))
         return FALSE;
 
+    virMutexLock(&ctl->mutex);
+    ctl->dom = dom;
+    virMutexUnlock(&ctl->mutex);
     desturi = vshCommandOptString (cmd, "desturi", &found);
     if (!found)
         goto done;
@@ -3454,6 +3514,9 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd)
     }
 
  done:
+    virMutexLock(&ctl->mutex);
+    ctl->dom = NULL;
+    virMutexUnlock(&ctl->mutex);
     if (dom) virDomainFree (dom);
     return ret;
 }
@@ -10837,12 +10900,15 @@ vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, char **name)
 /*
  * Executes command(s) and returns return code from last command
  */
-static int
-vshCommandRun(vshControl *ctl, const vshCmd *cmd)
+static void
+vshCommandRun(void *jobdata, void *opaque)
 {
+    vshControl *ctl = opaque;
+    vshCmd *cmds = jobdata;
+    vshCmd *cmd;
     int ret = TRUE;
 
-    while (cmd) {
+    while (cmds) {
         struct timeval before, after;
         bool enable_timing = ctl->timing;
 
@@ -10852,6 +10918,9 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd)
         if (enable_timing)
             GETTIMEOFDAY(&before);
 
+        cmd = cmds;
+        cmds = cmds->next;
+
         ret = cmd->def->handler(ctl, cmd);
 
         if (enable_timing)
@@ -10871,17 +10940,12 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd)
                (last_error->code == VIR_ERR_INVALID_CONN)))))
             vshReconnect(ctl);
 
-        if (STREQ(cmd->def->name, "quit"))        /* hack ... */
-            return ret;
-
         if (enable_timing)
             vshPrint(ctl, _("\n(Time: %.3f ms)\n\n"),
                      DIFF_MSEC(&after, &before));
         else
             vshPrintExtra(ctl, "\n");
-        cmd = cmd->next;
     }
-    return ret;
 }
 
 /* ---------------
@@ -11284,6 +11348,9 @@ vshInit(vshControl *ctl)
     if (ctl->conn)
         return FALSE;
 
+    if (virMutexInit(&ctl->mutex) < 0)
+        return FALSE;
+
     vshOpenLogFile(ctl);
 
     /* set up the library error handler */
@@ -11315,6 +11382,12 @@ vshInit(vshControl *ctl)
         return FALSE;
     }
 
+    ctl->threadPool = virThreadPoolNew(0, 2, vshCommandRun, ctl);
+    if (!ctl->threadPool) {
+        return FALSE;
+    }
+
+
     return TRUE;
 }
 
@@ -11669,6 +11742,7 @@ vshReadline (vshControl *ctl, const char *prompt)
 static int
 vshDeinit(vshControl *ctl)
 {
+    virThreadPoolFree(ctl->threadPool);
     vshReadlineDeinit(ctl);
     vshCloseLogFile(ctl);
     VIR_FREE(ctl->name);
@@ -11938,7 +12012,7 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
 int
 main(int argc, char **argv)
 {
-    vshControl _ctl, *ctl = &_ctl;
+    vshControl *ctl = &_ctl;
     char *defaultConn;
     int ret = TRUE;
 
@@ -11979,7 +12053,16 @@ main(int argc, char **argv)
     }
 
     if (!ctl->imode) {
-        ret = vshCommandRun(ctl, ctl->cmd);
+        vshCmd *cmds, *c;
+
+        cmds = ctl->cmd;
+        ctl->cmd = NULL;
+        do {
+            c = cmds;
+            cmds = cmds->next;
+            c->next = NULL;
+            ignore_value(virThreadPoolSendJob(ctl->threadPool, c, true));
+        } while (cmds);
     } else {
         /* interactive mode */
         if (!ctl->quiet) {
@@ -11997,6 +12080,7 @@ main(int argc, char **argv)
         }
 
         do {
+            vshCmd *cmds, *c;
             const char *prompt = ctl->readonly ? VSH_PROMPT_RO : VSH_PROMPT_RW;
             ctl->cmdstr =
                 vshReadline(ctl, prompt);
@@ -12006,8 +12090,16 @@ main(int argc, char **argv)
 #if USE_READLINE
                 add_history(ctl->cmdstr);
 #endif
-                if (vshCommandStringParse(ctl, ctl->cmdstr))
-                    vshCommandRun(ctl, ctl->cmd);
+                if (vshCommandStringParse(ctl, ctl->cmdstr)) {
+                    cmds = ctl->cmd;
+                    ctl->cmd = NULL;
+                    do {
+                        c = cmds;
+                        cmds = cmds->next;
+                        c->next = NULL;
+                        ignore_value(virThreadPoolSendJob(ctl->threadPool, c, true));
+                    } while (cmds);
+                }
             }
             VIR_FREE(ctl->cmdstr);
         } while (ctl->imode);
-- 
1.7.3.1


-- 
Thanks,
Hu Tao




More information about the libvir-list mailing list