---
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