From: Jiri Denemark Date: Tue, 11 Oct 2011 13:05:52 +0000 (+0200) Subject: virsh: Always run event loop X-Git-Tag: v0.9.8-rc1~86 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fd7e85ac6af833845aa0eb2526158c319800a0ae;p=thirdparty%2Flibvirt.git virsh: Always run event loop Since virsh already implements event loop, it has to also run it. So far the event loop was only running during virsh console command. --- diff --git a/tools/console.c b/tools/console.c index 0f85bc70db..e9e01a4675 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 50fc98d6fb..16d815c9ad 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -250,6 +250,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 { @@ -16636,6 +16639,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. */ @@ -16681,6 +16697,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, @@ -17069,6 +17089,7 @@ vshReadline (vshControl *ctl, const char *prompt) static bool vshDeinit(vshControl *ctl) { + ctl->quit = true; vshReadlineDeinit(ctl); vshCloseLogFile(ctl); VIR_FREE(ctl->name); @@ -17080,6 +17101,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; }