Since virsh already implements event loop, it has to also run it. So far
the event loop was only running during virsh console command.
---
Notes:
ACKed
Version 4:
- no changes
Version 3:
- new patch
tools/console.c | 17 ++++++++++++++---
tools/virsh.c | 31 +++++++++++++++++++++++++++++++
2 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/tools/console.c b/tools/console.c
index 0f85bc7..e9e01a4 100644
--- a/tools/console.c
+++ b/tools/console.c
@@ -41,6 +41,7 @@
# include "util.h"
# include "virfile.h"
# include "memory.h"
+# include "threads.h"
# include "virterror_internal.h"
@@ -60,6 +61,8 @@ typedef virConsole *virConsolePtr;
struct virConsole {
virStreamPtr st;
bool quit;
+ virMutex lock;
+ virCond cond;
int stdinWatch;
int stdoutWatch;
@@ -89,7 +92,6 @@ cfmakeraw (struct termios *attr)
static void
virConsoleShutdown(virConsolePtr con)
{
- con->quit = true;
if (con->st) {
virStreamEventRemoveCallback(con->st);
virStreamAbort(con->st);
@@ -101,6 +103,8 @@ virConsoleShutdown(virConsolePtr con)
virEventRemoveHandle(con->stdoutWatch);
con->stdinWatch = -1;
con->stdoutWatch = -1;
+ con->quit = true;
+ virCondSignal(&con->cond);
}
static void
@@ -334,6 +338,9 @@ int vshRunConsole(virDomainPtr dom, const char *dev_name)
if (virDomainOpenConsole(dom, dev_name, con->st, 0) < 0)
goto cleanup;
+ if (virCondInit(&con->cond) < 0 || virMutexInit(&con->lock) < 0)
+ goto cleanup;
+
con->stdinWatch = virEventAddHandle(STDIN_FILENO,
VIR_EVENT_HANDLE_READABLE,
virConsoleEventOnStdin,
@@ -352,8 +359,10 @@ int vshRunConsole(virDomainPtr dom, const char *dev_name)
NULL);
while (!con->quit) {
- if (virEventRunDefaultImpl() < 0)
- break;
+ if (virCondWait(&con->cond, &con->lock) < 0) {
+ VIR_ERROR(_("unable to wait on console condition"));
+ goto cleanup;
+ }
}
ret = 0;
@@ -363,6 +372,8 @@ int vshRunConsole(virDomainPtr dom, const char *dev_name)
if (con) {
if (con->st)
virStreamFree(con->st);
+ virMutexDestroy(&con->lock);
+ ignore_value(virCondDestroy(&con->cond));
VIR_FREE(con);
}
diff --git a/tools/virsh.c b/tools/virsh.c
index 72344f0..9ed9a04 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -249,6 +249,9 @@ typedef struct __vshControl {
virDomainGetState is not supported */
bool useSnapshotOld; /* cannot use virDomainSnapshotGetParent or
virDomainSnapshotNumChildren */
+ virThread eventLoop;
+ bool eventLoopStarted;
+ bool quit;
} __vshControl;
typedef struct vshCmdGrp {
@@ -15954,6 +15957,19 @@ vshError(vshControl *ctl, const char *format, ...)
}
+static void
+vshEventLoop(void *opaque)
+{
+ vshControl *ctl = opaque;
+
+ while (!ctl->quit) {
+ if (virEventRunDefaultImpl() < 0) {
+ virshReportError(ctl);
+ }
+ }
+}
+
+
/*
* Initialize connection.
*/
@@ -15999,6 +16015,10 @@ vshInit(vshControl *ctl)
if (virEventRegisterDefaultImpl() < 0)
return false;
+ if (virThreadCreate(&ctl->eventLoop, true, vshEventLoop, ctl) < 0)
+ return false;
+ ctl->eventLoopStarted = true;
+
if (ctl->name) {
ctl->conn = virConnectOpenAuth(ctl->name,
virConnectAuthPtrDefault,
@@ -16387,6 +16407,7 @@ vshReadline (vshControl *ctl, const char *prompt)
static bool
vshDeinit(vshControl *ctl)
{
+ ctl->quit = true;
vshReadlineDeinit(ctl);
vshCloseLogFile(ctl);
VIR_FREE(ctl->name);
@@ -16398,6 +16419,16 @@ vshDeinit(vshControl *ctl)
}
virResetLastError();
+ if (ctl->eventLoopStarted) {
+ /* HACK: Add a dummy timeout to break event loop */
+ int timer = virEventAddTimeout(-1, NULL, NULL, NULL);
+ if (timer != -1)
+ virEventRemoveTimeout(timer);
+
+ virThreadJoin(&ctl->eventLoop);
+ ctl->eventLoopStarted = false;
+ }
+
return true;
}
--
1.7.7.1