--- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list