Not only was ctl->quit accessed without a mutex but unfortunately, virEventAddTimeout only interrupts the poll when event loop is running so the hack needs to add a timeout that will make next poll return immediately without blocking. --- tools/virsh.c | 39 +++++++++++++++++++++++++++++++++------ 1 files changed, 33 insertions(+), 6 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 618b0c1..723ec65 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -251,6 +251,7 @@ typedef struct __vshControl { bool useSnapshotOld; /* cannot use virDomainSnapshotGetParent or virDomainSnapshotNumChildren */ virThread eventLoop; + virMutex lock; bool eventLoopStarted; bool quit; } __vshControl; @@ -16796,10 +16797,17 @@ vshEventLoop(void *opaque) { vshControl *ctl = opaque; - while (!ctl->quit) { - if (virEventRunDefaultImpl() < 0) { + while (1) { + bool quit; + virMutexLock(&ctl->lock); + quit = ctl->quit; + virMutexUnlock(&ctl->lock); + + if (quit) + break; + + if (virEventRunDefaultImpl() < 0) virshReportError(ctl); - } } } @@ -17235,13 +17243,18 @@ vshReadline (vshControl *ctl, const char *prompt) #endif /* !USE_READLINE */ +static void +vshDeinitTimer(int timer ATTRIBUTE_UNUSED, void *opaque ATTRIBUTE_UNUSED) +{ + /* nothing to be done here */ +} + /* * Deinitialize virsh */ static bool vshDeinit(vshControl *ctl) { - ctl->quit = true; vshReadlineDeinit(ctl); vshCloseLogFile(ctl); VIR_FREE(ctl->name); @@ -17254,15 +17267,24 @@ vshDeinit(vshControl *ctl) virResetLastError(); if (ctl->eventLoopStarted) { + int timer; + + virMutexLock(&ctl->lock); + ctl->quit = true; /* HACK: Add a dummy timeout to break event loop */ - int timer = virEventAddTimeout(-1, NULL, NULL, NULL); + timer = virEventAddTimeout(0, vshDeinitTimer, NULL, NULL); + virMutexUnlock(&ctl->lock); + + virThreadJoin(&ctl->eventLoop); + if (timer != -1) virEventRemoveTimeout(timer); - virThreadJoin(&ctl->eventLoop); ctl->eventLoopStarted = false; } + virMutexDestroy(&ctl->lock); + return true; } @@ -17543,6 +17565,11 @@ main(int argc, char **argv) return EXIT_FAILURE; } + if (virMutexInit(&ctl->lock) < 0) { + vshError(ctl, "%s", _("Failed to initialize mutex")); + return EXIT_FAILURE; + } + if (virInitialize() < 0) { vshError(ctl, "%s", _("Failed to initialize libvirt")); return EXIT_FAILURE; -- 1.7.8.rc4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list