[ This is also filed in Red Hat's bugzilla at
https://bugzilla.redhat.com/show_bug.cgi?id=537938 ]
In cases where compression is in use, putting the waitpid() for the
decompression tool before the qemudWaitForMonitor() call appears to
eliminate the race in question.
As much of a cheap hack as it is, it seems like it would resolve the
race condition in question to always spawn and block on an intermediate
process, even if this means having *two* "cat" processes between
libvirtd and the qemu or kvm it is starting.
Comments?
--- libvirt-0.7.2/src/qemu/qemu_driver.c.orig 2009-11-18 17:30:52.502986557 -0600
+++ libvirt-0.7.2/src/qemu/qemu_driver.c 2009-11-18 17:37:30.414042960 -0600
@@ -100,7 +100,9 @@
struct qemud_driver *driver,
virDomainObjPtr vm,
const char *migrateFrom,
- int stdin_fd);
+ int stdin_fd,
+ int intermediate_pid,
+ int intermediate_fd);
static void qemudShutdownVMDaemon(virConnectPtr conn,
struct qemud_driver *driver,
@@ -223,7 +225,7 @@
int ret;
virResetLastError();
- ret = qemudStartVMDaemon(conn, driver, vm, NULL, -1);
+ ret = qemudStartVMDaemon(conn, driver, vm, NULL, -1, -1, -1);
if (ret < 0) {
virErrorPtr err = virGetLastError();
VIR_ERROR(_("Failed to autostart VM '%s': %s\n"),
@@ -1941,7 +1943,9 @@
struct qemud_driver *driver,
virDomainObjPtr vm,
const char *migrateFrom,
- int stdin_fd) {
+ int stdin_fd,
+ int intermediate_pid,
+ int intermediate_fd) {
const char **argv = NULL, **tmp;
const char **progenv = NULL;
int i, ret;
@@ -1956,6 +1960,7 @@
char ebuf[1024];
char *pidfile = NULL;
int logfile;
+ int childstat;
struct qemudHookData hookData;
hookData.conn = conn;
@@ -2131,6 +2136,14 @@
if (ret == -1)
goto cleanup;
+ if (intermediate_pid != -1) {
+ /* Wait for intermediate process to exit */
+ while (waitpid(intermediate_pid, &childstat, 0) == -1 &&
+ errno == EINTR);
+ }
+ if (intermediate_fd != -1)
+ close(intermediate_fd);
+
if ((qemudWaitForMonitor(conn, driver, vm, pos) < 0) ||
(qemuDetectVcpuPIDs(conn, vm) < 0) ||
(qemudInitCpus(conn, vm, migrateFrom) < 0) ||
@@ -2723,7 +2736,7 @@
def = NULL;
- if (qemudStartVMDaemon(conn, driver, vm, NULL, -1) < 0) {
+ if (qemudStartVMDaemon(conn, driver, vm, NULL, -1, -1, -1) < 0) {
virDomainRemoveInactive(&driver->domains,
vm);
vm = NULL;
@@ -3837,14 +3850,8 @@
}
}
/* Set the migration source and start it up. */
- ret = qemudStartVMDaemon(conn, driver, vm, "stdio", fd);
- if (intermediate_pid != -1) {
- /* Wait for intermediate process to exit */
- while (waitpid(intermediate_pid, &childstat, 0) == -1 &&
- errno == EINTR);
- }
- if (intermediatefd != -1)
- close(intermediatefd);
+ ret = qemudStartVMDaemon(conn, driver, vm, "stdio", fd,
+ intermediate_pid, intermediatefd);
close(fd);
fd = -1;
if (ret < 0) {
@@ -4144,7 +4151,7 @@
goto cleanup;
}
- ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL, -1);
+ ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL, -1, -1, -1);
if (ret != -1)
event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STARTED,
@@ -6209,7 +6216,7 @@
/* Start the QEMU daemon, with the same command-line arguments plus
* -incoming unix:/path/to/file or exec:nc -U /path/to/file
*/
- internalret = qemudStartVMDaemon(dconn, driver, vm, migrateFrom, -1);
+ internalret = qemudStartVMDaemon(dconn, driver, vm, migrateFrom, -1, -1, -1);
VIR_FREE(migrateFrom);
if (internalret < 0) {
/* Note that we don't set an error here because qemudStartVMDaemon
@@ -6404,7 +6411,7 @@
* -incoming tcp:0.0.0.0:port
*/
snprintf (migrateFrom, sizeof (migrateFrom), "tcp:0.0.0.0:%d", this_port);
- if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, -1) < 0) {
+ if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, -1, -1, -1) < 0) {
/* Note that we don't set an error here because qemudStartVMDaemon
* should have already done that.
*/
--
Libvir-list mailing list
Libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list