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: 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 bcf0603..1434697 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -248,6 +248,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 { @@ -15843,6 +15846,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. */ @@ -15888,6 +15904,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, @@ -16276,6 +16296,7 @@ vshReadline (vshControl *ctl, const char *prompt) static bool vshDeinit(vshControl *ctl) { + ctl->quit = true; vshReadlineDeinit(ctl); vshCloseLogFile(ctl); VIR_FREE(ctl->name); @@ -16287,6 +16308,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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list