mirror of
https://github.com/libvirt/libvirt.git
synced 2026-10-02 12:20:06 -05:00
virFork: give specific status on failure prior to exec
When a child fails without exec'ing, we want a well-known status; best is to match what env(1), nice(1), su(1), and other wrapper programs do. This patch adds enum values that later patches will use, and sets up virFork as the first client of EXIT_CANCELED for errors detected prior to even attempting exec, as well as virExec to distinguish between a missing executable vs. a binary that cannot be executed. This is a slight semantic change in the unlikely case of a child process failing to restore its signal mask - we now kill the child with a known status instead of relying on the caller to notice and do an appropriate _exit(). A subsequent patch will make further cleanups based on an audit of all callers. * src/internal.h (EXIT_CANCELED, EXIT_CANNOT_INVOKE) (EXIT_ENOENT): New enum. * src/util/vircommand.c (virFork): Document specific exit value if child aborts early. (virExec): Distinguish between various exec failures. * tests/commandtest.c (test1): Enhance test. (test22): New test. Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
1 parent
f972a7c72c
commit
631923e7f2
3 files changed
+57
-8
No files matched your search
+41
-2
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* commandtest.c: Test the libCommand API
|
||||
*
|
||||
* Copyright (C) 2010-2013 Red Hat, Inc.
|
||||
* Copyright (C) 2010-2014 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -140,7 +140,7 @@ static int test1(const void *unused ATTRIBUTE_UNUSED)
|
||||
cmd = virCommandNew(abs_builddir "/commandhelper-doesnotexist");
|
||||
if (virCommandRun(cmd, &status) < 0)
|
||||
goto cleanup;
|
||||
if (status == 0)
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_ENOENT)
|
||||
goto cleanup;
|
||||
ret = 0;
|
||||
|
||||
@@ -899,6 +899,44 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
test22(const void *unused ATTRIBUTE_UNUSED)
|
||||
{
|
||||
int ret = -1;
|
||||
virCommandPtr cmd;
|
||||
int status = -1;
|
||||
|
||||
cmd = virCommandNewArgList("/bin/sh", "-c", "exit 3", NULL);
|
||||
|
||||
if (virCommandRun(cmd, &status) < 0) {
|
||||
virErrorPtr err = virGetLastError();
|
||||
printf("Cannot run child %s\n", err->message);
|
||||
goto cleanup;
|
||||
}
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status) != 3) {
|
||||
printf("Unexpected status %d\n", status);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
virCommandFree(cmd);
|
||||
cmd = virCommandNewArgList("/bin/sh", "-c", "kill -9 $$", NULL);
|
||||
|
||||
if (virCommandRun(cmd, &status) < 0) {
|
||||
virErrorPtr err = virGetLastError();
|
||||
printf("Cannot run child %s\n", err->message);
|
||||
goto cleanup;
|
||||
}
|
||||
if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGKILL) {
|
||||
printf("Unexpected status %d\n", status);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
virCommandFree(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void virCommandThreadWorker(void *opaque)
|
||||
{
|
||||
virCommandTestDataPtr test = opaque;
|
||||
@@ -1046,6 +1084,7 @@ mymain(void)
|
||||
DO_TEST(test19);
|
||||
DO_TEST(test20);
|
||||
DO_TEST(test21);
|
||||
DO_TEST(test22);
|
||||
|
||||
virMutexLock(&test->lock);
|
||||
if (test->running) {
|
||||
|
||||
Reference in new issue
Block a user