]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
virsh-domain: Avoid killing ssh transport tunnels when cancelling job
authorPeter Krempa <pkrempa@redhat.com>
Thu, 29 Aug 2013 13:18:20 +0000 (15:18 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Tue, 3 Sep 2013 07:55:27 +0000 (09:55 +0200)
The vshWatchJob function registers a SIGINT handler that is used to
abort the active job and does not terminate virsh. Unfortunately, this
breaks when using the ssh transport as SIGINT is sent to the foreground
process group including the ssh transport processes which terminate.
This breaks the connection and migration is left in a insane state.

With this patch the terminal is modified to ignore key binding that
sends SIGINT and does the handling manually.

Resoves: https://bugzilla.redhat.com/show_bug.cgi?id=983348

tools/virsh-domain.c

index 568d61d001b47fd3a3fc149912ea45f7cafb52f1..88bdb52106a5d6c8a1a4eb8d5c904686e2009fbc 100644 (file)
@@ -3522,13 +3522,15 @@ vshWatchJob(vshControl *ctl,
 {
     struct sigaction sig_action;
     struct sigaction old_sig_action;
-    struct pollfd pollfd;
+    struct pollfd pollfd[2] = {{.fd = pipe_fd, .events = POLLIN, .revents = 0},
+                               {.fd = STDIN_FILENO, .events = POLLIN, .revents = 0}};
     struct timeval start, curr;
     virDomainJobInfo jobinfo;
     int ret = -1;
     char retchar;
     bool functionReturn = false;
     sigset_t sigmask, oldsigmask;
+    bool jobStarted = false;
 
     sigemptyset(&sigmask);
     sigaddset(&sigmask, SIGINT);
@@ -3539,16 +3541,21 @@ vshWatchJob(vshControl *ctl,
     sigemptyset(&sig_action.sa_mask);
     sigaction(SIGINT, &sig_action, &old_sig_action);
 
-    pollfd.fd = pipe_fd;
-    pollfd.events = POLLIN;
-    pollfd.revents = 0;
-
     GETTIMEOFDAY(&start);
     while (1) {
-repoll:
-        ret = poll(&pollfd, 1, 500);
+        ret = poll((struct pollfd *)&pollfd, 2, 500);
         if (ret > 0) {
-            if (pollfd.revents & POLLIN &&
+            if (pollfd[1].revents & POLLIN &&
+                saferead(STDIN_FILENO, &retchar, sizeof(retchar)) > 0) {
+                if (vshTTYIsInterruptCharacter(ctl, retchar)) {
+                    virDomainAbortJob(dom);
+                    goto cleanup;
+                } else {
+                    continue;
+                }
+            }
+
+            if (pollfd[0].revents & POLLIN &&
                 saferead(pipe_fd, &retchar, sizeof(retchar)) > 0 &&
                 retchar == '0') {
                 if (verbose) {
@@ -3566,7 +3573,7 @@ repoll:
                     virDomainAbortJob(dom);
                     intCaught = 0;
                 } else {
-                    goto repoll;
+                    continue;
                 }
             }
             goto cleanup;
@@ -3583,13 +3590,24 @@ repoll:
             timeout = 0;
         }
 
-        if (verbose) {
+        if (verbose || !jobStarted) {
             pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask);
             ret = virDomainGetJobInfo(dom, &jobinfo);
             pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL);
-            if (ret == 0)
-                vshPrintJobProgress(label, jobinfo.dataRemaining,
-                                    jobinfo.dataTotal);
+            if (ret == 0) {
+                if (verbose)
+                    vshPrintJobProgress(label, jobinfo.dataRemaining,
+                                        jobinfo.dataTotal);
+
+                if (!jobStarted &&
+                    (jobinfo.type == VIR_DOMAIN_JOB_BOUNDED ||
+                     jobinfo.type == VIR_DOMAIN_JOB_UNBOUNDED)) {
+                    vshTTYDisableInterrupt(ctl);
+                    jobStarted = true;
+                }
+            } else {
+                vshResetLibvirtError();
+            }
         }
     }
 
@@ -3597,6 +3615,7 @@ repoll:
 
 cleanup:
     sigaction(SIGINT, &old_sig_action, NULL);
+    vshTTYRestore(ctl);
     return functionReturn;
 }