# include "util.h"
# include "virfile.h"
# include "memory.h"
+# include "threads.h"
# include "virterror_internal.h"
struct virConsole {
virStreamPtr st;
bool quit;
+ virMutex lock;
+ virCond cond;
int stdinWatch;
int stdoutWatch;
static void
virConsoleShutdown(virConsolePtr con)
{
- con->quit = true;
if (con->st) {
virStreamEventRemoveCallback(con->st);
virStreamAbort(con->st);
virEventRemoveHandle(con->stdoutWatch);
con->stdinWatch = -1;
con->stdoutWatch = -1;
+ con->quit = true;
+ virCondSignal(&con->cond);
}
static void
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,
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;
if (con) {
if (con->st)
virStreamFree(con->st);
+ virMutexDestroy(&con->lock);
+ ignore_value(virCondDestroy(&con->cond));
VIR_FREE(con);
}
virDomainGetState is not supported */
bool useSnapshotOld; /* cannot use virDomainSnapshotGetParent or
virDomainSnapshotNumChildren */
+ virThread eventLoop;
+ bool eventLoopStarted;
+ bool quit;
} __vshControl;
typedef struct vshCmdGrp {
}
+static void
+vshEventLoop(void *opaque)
+{
+ vshControl *ctl = opaque;
+
+ while (!ctl->quit) {
+ if (virEventRunDefaultImpl() < 0) {
+ virshReportError(ctl);
+ }
+ }
+}
+
+
/*
* Initialize connection.
*/
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,
static bool
vshDeinit(vshControl *ctl)
{
+ ctl->quit = true;
vshReadlineDeinit(ctl);
vshCloseLogFile(ctl);
VIR_FREE(ctl->name);
}
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;
}