]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
virCommandExec: Report error if execve fails
authorMichal Privoznik <mprivozn@redhat.com>
Mon, 11 Jul 2016 14:03:34 +0000 (16:03 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 12 Jul 2016 11:34:35 +0000 (13:34 +0200)
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@redhat.com>
src/util/vircommand.c
tests/commandtest.c

index f5bd7af5e8a1890d39d91425e9fb1b1baac21aca..3c67c907aada1ffcc9fe495cb03be1d30ba114d2 100644 (file)
@@ -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)
index f433ad72efa1c37d1c3c8aebf6aad7533df47e11..2b77b9b6d9edb2100a4a9d59083e3f4cfbb0db34 100644 (file)
@@ -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) {