Due to the TTY layer, sending "\n" to the qemu monitor translates into "\r\n" when received. This triggers a bug in older versions of QEMU (KVM <= 33) because the same command is executed twice, and still has problems with fixed QEMU because the "(qemu)" prompt is printed twice. Switch all monitor commands to end with "\r" which avoids both issues. The QEMU monitor sends frequent terminal escape sequences, typically \033[D and \033[K. At times, these interfere with the prompt detection when they get sent between "\n" and "(qemu) ". Fix the issue by filtering out these sequences when they are received. Signed-off-by: Jim Paris <jim@xxxxxxxx> --- src/qemu_driver.c | 21 ++++++++++++++++----- 1 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/qemu_driver.c b/src/qemu_driver.c index b05c3f6..8063ad2 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -1306,12 +1306,14 @@ static int qemudMonitorCommand(struct qemud_driver *driver ATTRIBUTE_UNUSED, for (;;) { struct pollfd fd = { vm->monitor, POLLIN | POLLERR | POLLHUP, 0 }; char *tmp; + int skip = 0; /* Read all the data QEMU has sent thus far */ for (;;) { char data[1024]; int got = read(vm->monitor, data, sizeof(data)); char *b; + int i; if (got == 0) { if (buf) @@ -1333,14 +1335,23 @@ static int qemudMonitorCommand(struct qemud_driver *driver ATTRIBUTE_UNUSED, return -1; } buf = b; - memmove(buf+size, data, got); - buf[size+got] = '\0'; - size += got; + + /* Copy data, skipping 3-byte escape sequences */ + for (i = 0; i < got; i++) { + if (data[i] == '\033') + skip = 3; + if (skip) + skip--; + else + buf[size++] = data[i]; + } + buf[size] = '\0'; } if (buf) qemudDebug("Mon [%s]", buf); /* Look for QEMU prompt to indicate completion */ if (buf && ((tmp = strstr(buf, "\n(qemu) ")) != NULL)) { + fprintf(stderr,"got qemu\n"); tmp[0] = '\0'; break; } @@ -1755,7 +1766,7 @@ static int qemudDomainSuspend(virDomainPtr dom) { if (vm->state == VIR_DOMAIN_PAUSED) return 0; - if (qemudMonitorCommand(driver, vm, "stop\n", &info) < 0) { + if (qemudMonitorCommand(driver, vm, "stop\r", &info) < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "suspend operation failed"); return -1; } @@ -1780,7 +1791,7 @@ static int qemudDomainResume(virDomainPtr dom) { } if (vm->state == VIR_DOMAIN_RUNNING) return 0; - if (qemudMonitorCommand(driver, vm, "cont\n", &info) < 0) { + if (qemudMonitorCommand(driver, vm, "cont\r", &info) < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "resume operation failed"); return -1; } -- 1.5.3.rc4 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list