diff --git a/tools/virsh.c b/tools/virsh.c index a1317e896e..993dba69eb 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -3092,26 +3092,36 @@ static const vshCmdOptDef opts_dump[] = { {"reset", VSH_OT_BOOL, 0, N_("reset the domain after core dump")}, {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("where to dump the core")}, + {"verbose", VSH_OT_BOOL, 0, N_("display the progress of dump")}, {NULL, 0, 0, NULL} }; -static bool -cmdDump(vshControl *ctl, const vshCmd *cmd) +static void +doDump(void *opaque) { - virDomainPtr dom; + char ret = '1'; + vshCtrlData *data = opaque; + vshControl *ctl = data->ctl; + const vshCmd *cmd = data->cmd; + virDomainPtr dom = NULL; + sigset_t sigmask, oldsigmask; const char *name = NULL; const char *to = NULL; - bool ret = false; unsigned int flags = 0; + sigemptyset(&sigmask); + sigaddset(&sigmask, SIGINT); + if (pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask) < 0) + goto out_sig; + if (!vshConnectionUsability(ctl, ctl->conn)) - return false; + goto out; if (vshCommandOptString(cmd, "file", &to) <= 0) - return false; + goto out; if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) - return false; + goto out; if (vshCommandOptBool (cmd, "live")) flags |= VIR_DUMP_LIVE; @@ -3124,14 +3134,63 @@ cmdDump(vshControl *ctl, const vshCmd *cmd) if (virDomainCoreDump(dom, to, flags) < 0) { vshError(ctl, _("Failed to core dump domain %s to %s"), name, to); - goto cleanup; + goto out; } - vshPrint(ctl, _("Domain %s dumped to %s\n"), name, to); - ret = true; + ret = '0'; +out: + pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL); +out_sig: + if (dom) + virDomainFree (dom); + ignore_value(safewrite(data->writefd, &ret, sizeof(ret))); +} + +static bool +cmdDump(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom; + int p[2] = { -1, -1}; + bool ret = false; + bool verbose = false; + const char *name = NULL; + const char *to = NULL; + vshCtrlData data; + virThread workerThread; + + if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + return false; + + if (vshCommandOptString(cmd, "file", &to) <= 0) + return false; + + if (vshCommandOptBool (cmd, "verbose")) + verbose = true; + + if (pipe(p) < 0) + goto cleanup; + + data.ctl = ctl; + data.cmd = cmd; + data.writefd = p[1]; + + if (virThreadCreate(&workerThread, + true, + doDump, + &data) < 0) + goto cleanup; + + ret = vshWatchJob(ctl, dom, verbose, p[0], 0, NULL, NULL, _("Dump")); + + virThreadJoin(&workerThread); + + if (ret) + vshPrint(ctl, _("\nDomain %s dumped to %s\n"), name, to); cleanup: virDomainFree(dom); + VIR_FORCE_CLOSE(p[0]); + VIR_FORCE_CLOSE(p[1]); return ret; } diff --git a/tools/virsh.pod b/tools/virsh.pod index 7001209fa1..0c43ffae70 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -682,7 +682,7 @@ the I argument must be B. For Xen hypervisor, the I argument may be B or B. =item B I I [I<--bypass-cache>] -{ [I<--live>] | [I<--crash>] | [I<--reset>] } +{ [I<--live>] | [I<--crash>] | [I<--reset>] } [I<--verbose>] Dumps the core of a domain to a file for analysis. If I<--live> is specified, the domain continues to run until the core @@ -695,9 +695,9 @@ If I<--bypass-cache> is specified, the save will avoid the file system cache, although this may slow down the operation. The progress may be monitored using B virsh command and canceled -with B command (sent by another virsh instance). Interrupting -(usually with C) the virsh process which runs B command is not -enough to actually cancel the operation. +with B command (sent by another virsh instance). Another option +is to send SIGINT (usually with C) to the virsh process running +B command. I<--verbose> displays the progress of dump. NOTE: Some hypervisors may require the user to manually ensure proper permissions on file and path specified by argument I.