qemu: Report cmdline output if VM dies early

qemuReadLogOutput early VM death detection is racy and won't always work.
Startup then errors when connecting to the VM monitor. This won't report
the emulator cmdline output which is typically the most useful diagnostic.

Check if the VM has died at the very end of the monitor connection step,
and if so, report the cmdline output.

See also: https://bugzilla.redhat.com/show_bug.cgi?id=581381
This commit is contained in:
Cole Robinson 2010-05-17 10:15:53 -04:00
parent d536f6b177
commit 83be64034a

View File

@ -2034,39 +2034,47 @@ static void qemudFreePtyPath(void *payload, const char *name ATTRIBUTE_UNUSED)
VIR_FREE(payload); VIR_FREE(payload);
} }
static void
qemuReadLogFD(int logfd, char *buf, int maxlen, int off)
{
int ret;
char *tmpbuf = buf + off;
ret = saferead(logfd, tmpbuf, maxlen - off - 1);
if (ret < 0) {
ret = 0;
}
tmpbuf[ret] = '\0';
}
static int static int
qemudWaitForMonitor(struct qemud_driver* driver, qemudWaitForMonitor(struct qemud_driver* driver,
virDomainObjPtr vm, off_t pos) virDomainObjPtr vm, off_t pos)
{ {
char buf[4096]; /* Plenty of space to get startup greeting */ char buf[4096] = ""; /* Plenty of space to get startup greeting */
int logfd; int logfd;
int ret = -1; int ret = -1;
virHashTablePtr paths = NULL;
if ((logfd = qemudLogReadFD(driver->logDir, vm->def->name, pos)) if ((logfd = qemudLogReadFD(driver->logDir, vm->def->name, pos)) < 0)
< 0)
return -1; return -1;
ret = qemudReadLogOutput(vm, logfd, buf, sizeof(buf), if (qemudReadLogOutput(vm, logfd, buf, sizeof(buf),
qemudFindCharDevicePTYs, qemudFindCharDevicePTYs,
"console", 30); "console", 30) < 0)
if (close(logfd) < 0) { goto closelog;
char ebuf[4096];
VIR_WARN(_("Unable to close logfile: %s"),
virStrerror(errno, ebuf, sizeof ebuf));
}
if (ret < 0)
return -1;
VIR_DEBUG("Connect monitor to %p '%s'", vm, vm->def->name); VIR_DEBUG("Connect monitor to %p '%s'", vm, vm->def->name);
if (qemuConnectMonitor(driver, vm) < 0) if (qemuConnectMonitor(driver, vm) < 0) {
return -1; goto cleanup;
}
/* Try to get the pty path mappings again via the monitor. This is much more /* Try to get the pty path mappings again via the monitor. This is much more
* reliable if it's available. * reliable if it's available.
* Note that the monitor itself can be on a pty, so we still need to try the * Note that the monitor itself can be on a pty, so we still need to try the
* log output method. */ * log output method. */
virHashTablePtr paths = virHashCreate(0); paths = virHashCreate(0);
if (paths == NULL) { if (paths == NULL) {
virReportOOMError(); virReportOOMError();
goto cleanup; goto cleanup;
@ -2087,6 +2095,23 @@ cleanup:
virHashFree(paths, qemudFreePtyPath); virHashFree(paths, qemudFreePtyPath);
} }
if (kill(vm->pid, 0) == -1 && errno == ESRCH) {
/* VM is dead, any other error raised in the interim is probably
* not as important as the qemu cmdline output */
qemuReadLogFD(logfd, buf, sizeof(buf), strlen(buf));
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("process exited while connecting to monitor: %s"),
buf);
ret = -1;
}
closelog:
if (close(logfd) < 0) {
char ebuf[4096];
VIR_WARN(_("Unable to close logfile: %s"),
virStrerror(errno, ebuf, sizeof ebuf));
}
return ret; return ret;
} }