]> xenbits.xensource.com Git - libvirt.git/commitdiff
command: avoid hanging on daemon processes
authorEric Blake <eblake@redhat.com>
Tue, 21 Dec 2010 18:49:49 +0000 (11:49 -0700)
committerEric Blake <eblake@redhat.com>
Tue, 21 Dec 2010 18:49:49 +0000 (11:49 -0700)
* src/util/command.c (virCommandRun): Don't capture output on
daemons.
* tests/commandtest.c (test18): Expose the bug.
Reported by Laine Stump.

src/util/command.c
tests/commandtest.c

index f9d475e16fa178f57e522032deb02726e5f60573..abd2dc4ae4d4823d55a5c1702ec9a8cb015937ad 100644 (file)
@@ -1008,17 +1008,21 @@ virCommandRun(virCommandPtr cmd, int *exitstatus)
     }
 
     /* If caller hasn't requested capture of stdout/err, then capture
-     * it ourselves so we can log it.
+     * it ourselves so we can log it.  But the intermediate child for
+     * a daemon has no expected output, and we don't want our
+     * capturing pipes passed on to the daemon grandchild.
      */
-    if (!cmd->outfdptr) {
-        cmd->outfdptr = &cmd->outfd;
-        cmd->outbuf = &outbuf;
-        string_io = true;
-    }
-    if (!cmd->errfdptr) {
-        cmd->errfdptr = &cmd->errfd;
-        cmd->errbuf = &errbuf;
-        string_io = true;
+    if (!(cmd->flags & VIR_EXEC_DAEMON)) {
+        if (!cmd->outfdptr) {
+            cmd->outfdptr = &cmd->outfd;
+            cmd->outbuf = &outbuf;
+            string_io = true;
+        }
+        if (!cmd->errfdptr) {
+            cmd->errfdptr = &cmd->errfd;
+            cmd->errbuf = &errbuf;
+            string_io = true;
+        }
     }
 
     if (virCommandRunAsync(cmd, NULL) < 0) {
index 333dd4d57c34f141821330e57bb8de5fb7e07259..38a78166b2c704d8fada4614cd3144c496c02f87 100644 (file)
@@ -668,6 +668,47 @@ cleanup:
     return ret;
 }
 
+/*
+ * Run long-running daemon, to ensure no hang.
+ */
+static int test18(const void *unused ATTRIBUTE_UNUSED)
+{
+    virCommandPtr cmd = virCommandNewArgList("sleep", "100", NULL);
+    char *pidfile = virFilePid(abs_builddir, "commandhelper");
+    pid_t pid;
+    int ret = -1;
+
+    if (!pidfile)
+        goto cleanup;
+
+    virCommandSetPidFile(cmd, pidfile);
+    virCommandDaemonize(cmd);
+
+    alarm(5);
+    if (virCommandRun(cmd, NULL) < 0) {
+        virErrorPtr err = virGetLastError();
+        printf("Cannot run child %s\n", err->message);
+        goto cleanup;
+    }
+    alarm(0);
+
+    if (virFileReadPid(abs_builddir, "commandhelper", &pid) != 0) {
+        printf("cannot read pidfile\n");
+        goto cleanup;
+    }
+    while (kill(pid, SIGINT) != -1)
+        usleep(100*1000);
+
+    ret = 0;
+
+cleanup:
+    virCommandFree(cmd);
+    unlink(pidfile);
+    VIR_FREE(pidfile);
+    return ret;
+}
+
+
 static int
 mymain(int argc, char **argv)
 {
@@ -732,6 +773,7 @@ mymain(int argc, char **argv)
     DO_TEST(test15);
     DO_TEST(test16);
     DO_TEST(test17);
+    DO_TEST(test18);
 
     return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
 }