Current, we support run sync job and async job at the same time. It means that the monitor commands for two jobs can be run in any order. In the function qemuDomainObjEnterMonitorInternal(): if (priv->job.active == QEMU_JOB_NONE && priv->job.asyncJob) { if (qemuDomainObjBeginNestedJob(driver, obj) < 0) We check whether the caller is an async job by priv->job.active and priv->job.asynJob. But when an async job is running, priv->job.active is QEMU_JOB_NONE if no sync job is running, or priv->job.active is not QEMU_JOB_NONE if a sync job is running. So we cannot check whether the caller is an async job in the function qemuDomainObjEnterMonitorInternal(). Unfortunately, if sync job and async job are running at the same time, we may try to send monitor command at the same time in two threads. It's very dangerous, and it will cause libvirtd crashed. We should enhance the function qemuMonitorSend() to support it to be called at the same time. If the last monitor command does not finish, the other monitor commands should wait it to finish. --- src/qemu/qemu_monitor.c | 22 +++++++++++++++++++++- 1 files changed, 21 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index db6107c..a10f53f 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -46,6 +46,8 @@ struct _qemuMonitor { virMutex lock; /* also used to protect fd */ virCond notify; + virCond send_notify; + int refs; int fd; @@ -675,7 +677,8 @@ qemuMonitorOpen(virDomainObjPtr vm, VIR_FREE(mon); return NULL; } - if (virCondInit(&mon->notify) < 0) { + if ((virCondInit(&mon->notify) < 0) || + (virCondInit(&mon->send_notify) < 0)) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot initialize monitor condition")); virMutexDestroy(&mon->lock); @@ -795,6 +798,22 @@ int qemuMonitorSend(qemuMonitorPtr mon, return -1; } + while (mon->msg) { + if (virCondWait(&mon->send_notify, &mon->lock) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to wait on monitor condition")); + goto cleanup; + } + } + + /* Check whether qemu quited unexpectedly again */ + if (mon->lastError.code != VIR_ERR_OK) { + VIR_DEBUG("Attempt to send command while error is set %s", + NULLSTR(mon->lastError.message)); + virSetError(&mon->lastError); + return -1; + } + mon->msg = msg; qemuMonitorUpdateWatch(mon); @@ -818,6 +837,7 @@ int qemuMonitorSend(qemuMonitorPtr mon, cleanup: mon->msg = NULL; qemuMonitorUpdateWatch(mon); + virCondBroadcast(&mon->send_notify); return ret; } -- 1.7.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list