From: Eric Blake Date: Tue, 21 Dec 2010 18:49:49 +0000 (-0700) Subject: command: avoid hanging on daemon processes X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=c7f28dec60bcbaf95f5a419bb5a9cb5197089253;p=libvirt.git command: avoid hanging on daemon processes * src/util/command.c (virCommandRun): Don't capture output on daemons. * tests/commandtest.c (test18): Expose the bug. Reported by Laine Stump. --- diff --git a/src/util/command.c b/src/util/command.c index f9d475e16f..abd2dc4ae4 100644 --- a/src/util/command.c +++ b/src/util/command.c @@ -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) { diff --git a/tests/commandtest.c b/tests/commandtest.c index 333dd4d57c..38a78166b2 100644 --- a/tests/commandtest.c +++ b/tests/commandtest.c @@ -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); }