/*
* libvirtd.c: daemon start of day, guest process & i/o management
*
- * Copyright (C) 2006-2012 Red Hat, Inc.
+ * Copyright (C) 2006-2014 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
VIR_FORCE_CLOSE(statuspipe[1]);
/* We wait to make sure the first child forked successfully */
- if (virProcessWait(pid, NULL) < 0)
+ if (virProcessWait(pid, NULL, false) < 0)
goto error;
/* If we get here, then the grandchild was spawned, so we
virReportSystemError(errno, "%s",
_("Unable to clone to check reboot support"));
return -1;
- } else if (virProcessWait(cpid, &status) < 0) {
+ } else if (virProcessWait(cpid, &status, false) < 0) {
return -1;
}
- if (WEXITSTATUS(status) != 1) {
+ if (status != 1) {
VIR_DEBUG("Containerized reboot support is missing "
"(kernel probably too old < 3.4)");
return 0;
VIR_DEBUG("clone call returned %s, container support is not enabled",
virStrerror(errno, ebuf, sizeof(ebuf)));
return -1;
- } else if (virProcessWait(cpid, NULL) < 0) {
+ } else if (virProcessWait(cpid, NULL, false) < 0) {
return -1;
}
* message is not as detailed as what we can provide. So, we
* guarantee that virProcessWait only fails due to failure to wait,
* and repeat the exitstatus check code ourselves. */
- ret = virProcessWait(cmd->pid, exitstatus ? exitstatus : &status);
+ ret = virProcessWait(cmd->pid, exitstatus ? exitstatus : &status, true);
if (cmd->flags & VIR_EXEC_ASYNC_IO) {
cmd->flags &= ~VIR_EXEC_ASYNC_IO;
virThreadJoin(cmd->asyncioThread);
/*
* virfile.c: safer file handling
*
- * Copyright (C) 2010-2013 Red Hat, Inc.
+ * Copyright (C) 2010-2014 Red Hat, Inc.
* Copyright (C) 2010 IBM Corporation
* Copyright (C) 2010 Stefan Berger
* Copyright (C) 2010 Eric Blake
if (pid) { /* parent */
VIR_FREE(groups);
- if (virProcessWait(pid, &status) < 0) {
- /* virProcessWait() already
- * reported error */
- return -1;
- }
-
- if (!WIFEXITED(status)) {
- errno = EINTR;
+ if (virProcessWait(pid, &status, false) < 0) {
+ /* virProcessWait() already reported error */
return -1;
}
if (status) {
- errno = WEXITSTATUS(status);
+ errno = status;
return -1;
}
* virProcessWait:
* @pid: child to wait on
* @exitstatus: optional status collection
+ * @raw: whether to pass non-normal status back to caller
*
- * Wait for a child process to complete.
- * Return -1 on any error waiting for
- * completion. Returns 0 if the command
- * finished with the exit status set. If @exitstatus is NULL, then the
- * child must exit with status 0 for this to succeed.
+ * Wait for a child process to complete. If @exitstatus is NULL, then the
+ * child must exit normally with status 0. Otherwise, if @raw is false,
+ * the child must exit normally, and @exitstatus will contain the final
+ * exit status (no need for the caller to use WEXITSTATUS()). If @raw is
+ * true, then the result of wait() is returned in @exitstatus, and the
+ * caller must use WIFEXITED() and friends to decipher the child's status.
+ *
+ * Returns 0 on a successful wait. Returns -1 on any error waiting for
+ * completion, or if the command completed with a status that cannot be
+ * reflected via the choice of @exitstatus and @raw.
*/
int
-virProcessWait(pid_t pid, int *exitstatus)
+virProcessWait(pid_t pid, int *exitstatus, bool raw)
{
int ret;
int status;
}
if (exitstatus == NULL) {
- if (status != 0) {
- char *st = virProcessTranslateStatus(status);
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Child process (%lld) unexpected %s"),
- (long long) pid, NULLSTR(st));
- VIR_FREE(st);
- return -1;
- }
- } else {
+ if (status != 0)
+ goto error;
+ } else if (raw) {
*exitstatus = status;
+ } else if (WIFEXITED(status)) {
+ *exitstatus = WEXITSTATUS(status);
+ } else {
+ goto error;
}
return 0;
+
+error:
+ {
+ char *st = virProcessTranslateStatus(status);
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Child process (%lld) unexpected %s"),
+ (long long) pid, NULLSTR(st));
+ VIR_FREE(st);
+ }
+ return -1;
}
VIR_FORCE_CLOSE(errfd[1]);
ignore_value(virFileReadHeaderFD(errfd[0], 1024, &buf));
- ret = virProcessWait(child, &status);
+ ret = virProcessWait(child, &status, false);
if (!ret)
ret = status == EXIT_CANCELED ? -1 : status;
VIR_FREE(buf);
void virProcessExitWithStatus(int status) ATTRIBUTE_NORETURN;
int
-virProcessWait(pid_t pid, int *exitstatus)
+virProcessWait(pid_t pid, int *exitstatus, bool raw)
ATTRIBUTE_RETURN_CHECK;
int virProcessKill(pid_t pid, int sig);
_exit(EXIT_FAILURE);
if (pid == 0)
_exit(42);
- if (virProcessWait(pid, &status) < 0)
+ if (virProcessWait(pid, &status, true) < 0)
_exit(EXIT_FAILURE);
virProcessExitWithStatus(status);
_exit(EXIT_FAILURE);
}
- if (virProcessWait(pid, &status) < 0)
+ if (virProcessWait(pid, &status, true) < 0)
goto cleanup;
if (!WIFEXITED(status) || WEXITSTATUS(status) != 42) {
printf("Unexpected status %d\n", status);
raise(SIGKILL);
_exit(EXIT_FAILURE);
}
- if (virProcessWait(pid, &status) < 0)
+ if (virProcessWait(pid, &status, true) < 0)
_exit(EXIT_FAILURE);
virProcessExitWithStatus(status);
_exit(EXIT_FAILURE);
}
- if (virProcessWait(pid, &status) < 0)
+ if (virProcessWait(pid, &status, true) < 0)
goto cleanup;
if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGKILL) {
printf("Unexpected status %d\n", status);
/*
* testutils.c: basic test utils
*
- * Copyright (C) 2005-2013 Red Hat, Inc.
+ * Copyright (C) 2005-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
VIR_FORCE_CLOSE(pipefd[1]);
len = virFileReadLimFD(pipefd[0], maxlen, buf);
VIR_FORCE_CLOSE(pipefd[0]);
- if (virProcessWait(pid, NULL) < 0)
+ if (virProcessWait(pid, NULL, false) < 0)
return -1;
return len;
execv(cmdargv[0], cmdargv);
_exit(255);
} else {
- if (virProcessWait(pid, NULL) < 0)
+ if (virProcessWait(pid, NULL, false) < 0)
_exit(255);
}
_exit(0);
for (i = 0; i < nfdlist; i++)
VIR_FORCE_CLOSE(fdlist[i]);
VIR_FREE(fdlist);
- if (virProcessWait(pid, NULL) < 0)
+ if (virProcessWait(pid, NULL, false) < 0)
goto cleanup;
}
return EXIT_FAILURE;
}
}
- return virProcessWait(ccpid, &status2);
+ return virProcessWait(ccpid, &status2, true);
}
- ret = virProcessWait(cpid, &status);
+ ret = virProcessWait(cpid, &status, true);
cleanup:
virConfFree(conf);