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

Daniel P. Berrange berrange at redhat.com
Thu Jan 6 11:27:39 UTC 2011


On Thu, Jan 06, 2011 at 05:16:53PM +0800, Hu Tao wrote:
> While migration/dump is in progress and virsh is waiting for its
> completion, user may want to terminate the progress by pressing
> Ctrl-C. But virsh just exits on user's Ctrl-C leaving migration/dump
> in background that user isn't even aware of. It's not reasonable.
> 
> This patch changes the behaviour for migration/dump. For other
> commands Ctrl-C still terminates virsh itself.
> ---
> Hi Daniel, Eric,
> 
> This patch is entirely different from my previous implementation so
> not titled with v2. It's simpler than the previous one and introduces
> less changes: not introducing threadpool in virsh;Ctrl-C remains
> terminating virsh if no job in progress.
> 
> Thanks for your review of the previous patch.
> 
>  src/remote/remote_driver.c |    9 +++++++--
>  tools/virsh.c              |   37 +++++++++++++++++++++++++++++++++++--
>  2 files changed, 42 insertions(+), 4 deletions(-)
> 
> diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
> index ee2de4a..59ec486 100644
> --- a/src/remote/remote_driver.c
> +++ b/src/remote/remote_driver.c
> @@ -9810,7 +9810,7 @@ processCallDispatchReply(virConnectPtr conn ATTRIBUTE_UNUSED,
>          remoteError(VIR_ERR_RPC,
>                      _("no call waiting for reply with serial %d"),
>                      hdr->serial);
> -        return -1;
> +        return -2;
>      }
>  
>      if (hdr->proc != thecall->proc_nr) {
> @@ -10160,7 +10160,12 @@ remoteIOEventLoop(virConnectPtr conn,
>          }
>  
>          if (fds[0].revents & POLLIN) {
> -            if (remoteIOHandleInput(conn, priv, flags) < 0)
> +            int ret = remoteIOHandleInput(conn, priv, flags);
> +            if (ret == -2) {
> +                /* Not expected result, repoll */
> +                remoteDriverUnlock(priv);
> +                goto repoll;
> +            } else if (ret < 0)
>                  goto error;
>          }
>  

I don't think this change is correct. The error scenario shown
in the first chunk is one that is hit when you have malformed
data on the wire. As such I don't believe it is safe to treat
this as a non-fatal recoverable error. Hitting Ctrl-C may
well cause this path to behave as you desire, but there are
other non-Ctrl-C based scenarios in which is it incorrect.

While I think the threadpool stuff was overkill, we do still
need 1 extra thread and I think the solution / patch overlaps
with the solution/patch proposed by Wen Congyang a few days
ago.

eg, we can create a setup that looks like this which I think
will solve both your own & Wen's needs for migration in
virsh.

 * Thread a  (Runs the migration)

      pthread_sigmask(mask with SIGINT blocked)
      virDomainMigrate()
      pthread_sigmask(original mask)


 * Thread b  (Monitors/controls the migration)

     gettimeofday(start)
     while (1) {
        gettimeofday(now)
        if (now - start) > timeout
            force guest to offline migrate
        if intCatched == TRUE
            abort migrate
        if --verbose
            pthread_sigmask(mask with SIGINT blocked)
            virDomainGetJobInfo()
            pthread_sigmask(original mask)
            print out progress info on console
     }


Since thread a blocks Ctrl-C, the signal will get
delivered to thread b instead, possibly delayed a
little if in the (short) virDomainGetJobInfo call.
Thus we don't need any changes to remote_driver.c
at all, and virsh can handle Ctrl-C on its own.

> diff --git a/tools/virsh.c b/tools/virsh.c
> index 55e2a68..e4d431e 100644
> --- a/tools/virsh.c
> +++ b/tools/virsh.c
> @@ -492,6 +492,15 @@ out:
>      last_error = NULL;
>  }
>  
> +static bool intCatched = FALSE;
> +
> +static void vshCatchInt(int sig ATTRIBUTE_UNUSED,
> +                        siginfo_t *siginfo ATTRIBUTE_UNUSED,
> +                        void *context ATTRIBUTE_UNUSED)
> +{
> +    intCatched = TRUE;
> +}
> +
>  /*
>   * Detection of disconnections and automatic reconnection support
>   */
> @@ -1838,6 +1847,9 @@ cmdDump(vshControl *ctl, const vshCmd *cmd)
>      char *to;
>      int ret = TRUE;
>      int flags = 0;
> +    int result;
> +    struct sigaction sig_action;
> +    struct sigaction old_sig_action;
>  
>      if (!vshConnectionUsability(ctl, ctl->conn))
>          return FALSE;
> @@ -1848,18 +1860,27 @@ cmdDump(vshControl *ctl, const vshCmd *cmd)
>      if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
>          return FALSE;
>  
> +    sig_action.sa_sigaction = vshCatchInt;
> +    sig_action.sa_flags = SA_SIGINFO;
> +    sigemptyset(&sig_action.sa_mask);
> +    sigaction(SIGINT, &sig_action, &old_sig_action);
> +
>      if (vshCommandOptBool (cmd, "live"))
>          flags |= VIR_DUMP_LIVE;
>      if (vshCommandOptBool (cmd, "crash"))
>          flags |= VIR_DUMP_CRASH;
>  
> -    if (virDomainCoreDump(dom, to, flags) == 0) {
> +    result = virDomainCoreDump(dom, to, flags);
> +    if (result == 0) {
>          vshPrint(ctl, _("Domain %s dumped to %s\n"), name, to);
> +    } else if (intCatched) {
> +        virDomainAbortJob(dom);
>      } else {
>          vshError(ctl, _("Failed to core dump domain %s to %s"), name, to);
>          ret = FALSE;
>      }
>  
> +    sigaction(SIGINT, &old_sig_action, NULL);
>      virDomainFree(dom);
>      return ret;
>  }
> @@ -3388,6 +3409,9 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd)
>      const char *desturi;
>      const char *migrateuri;
>      const char *dname;
> +    int result;
> +    struct sigaction sig_action;
> +    struct sigaction old_sig_action;
>      int flags = 0, found, ret = FALSE;
>  
>      if (!vshConnectionUsability (ctl, ctl->conn))
> @@ -3396,6 +3420,11 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd)
>      if (!(dom = vshCommandOptDomain (ctl, cmd, NULL)))
>          return FALSE;
>  
> +    sig_action.sa_sigaction = vshCatchInt;
> +    sig_action.sa_flags = SA_SIGINFO;
> +    sigemptyset(&sig_action.sa_mask);
> +    sigaction(SIGINT, &sig_action, &old_sig_action);
> +
>      desturi = vshCommandOptString (cmd, "desturi", &found);
>      if (!found)
>          goto done;
> @@ -3437,6 +3466,8 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd)
>  
>          if (virDomainMigrateToURI (dom, desturi, flags, dname, 0) == 0)
>              ret = TRUE;
> +        else if (intCatched)
> +            virDomainAbortJob(dom);
>      } else {
>          /* For traditional live migration, connect to the destination host directly. */
>          virConnectPtr dconn = NULL;
> @@ -3449,11 +3480,13 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd)
>          if (ddom) {
>              virDomainFree(ddom);
>              ret = TRUE;
> -        }
> +        } else if (intCatched)
> +            virDomainAbortJob(dom);
>          virConnectClose (dconn);
>      }
>  
>   done:
> +    sigaction(SIGINT, &old_sig_action, NULL);
>      if (dom) virDomainFree (dom);
>      return ret;
>  }


Regards,
Daniel




More information about the libvir-list mailing list