In an unlikely event of execve() failing, the virCommandExec() function does not report any error, even though checks that are at the beginning of the function are verbose when failing. Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- diff to v1: - Fixed the test (used virFork() instead of plain fork(), prolonged the waiting time for child reply, ...) src/util/vircommand.c | 7 +++++- tests/commandtest.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/util/vircommand.c b/src/util/vircommand.c index f5bd7af..3c67c90 100644 --- a/src/util/vircommand.c +++ b/src/util/vircommand.c @@ -2152,7 +2152,12 @@ int virCommandExec(virCommandPtr cmd) return -1; } - return execve(cmd->args[0], cmd->args, cmd->env); + execve(cmd->args[0], cmd->args, cmd->env); + + virReportSystemError(errno, + _("cannot execute binary %s"), + cmd->args[0]); + return -1; } #else int virCommandExec(virCommandPtr cmd ATTRIBUTE_UNUSED) diff --git a/tests/commandtest.c b/tests/commandtest.c index f433ad7..2b77b9b 100644 --- a/tests/commandtest.c +++ b/tests/commandtest.c @@ -1063,6 +1063,74 @@ static int test24(const void *unused ATTRIBUTE_UNUSED) return ret; } + +static int test25(const void *unused ATTRIBUTE_UNUSED) +{ + int ret = -1; + int pipeFD[2] = { -1, -1}; + char rv = 0; + ssize_t tries = 100; + pid_t pid; + + if (pipe(pipeFD) < 0) { + fprintf(stderr, "Unable to create pipe\n"); + goto cleanup; + } + + if (virSetNonBlock(pipeFD[0]) < 0) { + fprintf(stderr, "Unable to make read end of pipe nonblocking\n"); + goto cleanup; + } + + /* Now, fork and try to exec a nonexistent binary. */ + pid = virFork(); + if (pid < 0) { + fprintf(stderr, "Unable to spawn child\n"); + goto cleanup; + } + + if (pid == 0) { + /* Child */ + virCommandPtr cmd = virCommandNew("some/nonexistent/binary"); + + rv = virCommandExec(cmd); + if (safewrite(pipeFD[1], &rv, sizeof(rv)) < 0) + fprintf(stderr, "Unable to write to pipe\n"); + _exit(EXIT_FAILURE); + } + + /* Parent */ + while (--tries) { + if (saferead(pipeFD[0], &rv, sizeof(rv)) < 0) { + if (errno != EWOULDBLOCK) { + fprintf(stderr, "Unable to read from pipe\n"); + goto cleanup; + } + + usleep(10 * 1000); + } else { + break; + } + } + + if (!tries) { + fprintf(stderr, "Child hasn't returned anything\n"); + goto cleanup; + } + + if (rv >= 0) { + fprintf(stderr, "Child should have returned an error\n"); + goto cleanup; + } + + ret = 0; + cleanup: + VIR_FORCE_CLOSE(pipeFD[0]); + VIR_FORCE_CLOSE(pipeFD[1]); + return ret; +} + + static void virCommandThreadWorker(void *opaque) { virCommandTestDataPtr test = opaque; @@ -1215,6 +1283,7 @@ mymain(void) DO_TEST(test22); DO_TEST(test23); DO_TEST(test24); + DO_TEST(test25); virMutexLock(&test->lock); if (test->running) { -- 2.8.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list