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.
This commit is contained in:
Eric Blake 2010-12-21 11:49:49 -07:00
parent 973ada0e0b
commit c7f28dec60
2 changed files with 56 additions and 10 deletions

View 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) {

View 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);
}