Move virProcess{Kill,Abort,TranslateStatus} into virprocess.{c,h}

Continue consolidation of process functions by moving some
helpers out of command.{c,h} into virprocess.{c,h}

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 9467ab6074)
This commit is contained in:
Daniel P. Berrange 2012-09-24 18:10:37 +01:00 committed by Cole Robinson
parent a5cf2ef4a7
commit a05d4ca932
13 changed files with 177 additions and 153 deletions

View File

@ -36,6 +36,7 @@
#include "virterror_internal.h"
#include "virfile.h"
#include "virpidfile.h"
#include "virprocess.h"
#define VIR_FROM_THIS VIR_FROM_QEMU

View File

@ -46,6 +46,7 @@
#include "virfile.h"
#include "virtypedparam.h"
#include "virdbus.h"
#include "virprocess.h"
#include "remote_protocol.h"
#include "qemu_protocol.h"

View File

@ -157,6 +157,7 @@ src/util/virnetdevvportprofile.c
src/util/virnetlink.c
src/util/virnodesuspend.c
src/util/virpidfile.c
src/util/virprocess.c
src/util/virrandom.c
src/util/virsocketaddr.c
src/util/virterror.c

View File

@ -162,12 +162,9 @@ virCommandSetPreExecHook;
virCommandSetWorkingDirectory;
virCommandToString;
virCommandTransferFD;
virProcessTranslateStatus;
virCommandWait;
virCommandWriteArgLog;
virFork;
virProcessAbort;
virProcessWait;
virRun;
@ -1709,7 +1706,11 @@ virPidFileDeletePath;
# virprocess.h
virProcessAbort;
virProcessKill;
virProcessTranslateStatus;
virProcessWait;
# virrandom.h
virRandom;

View File

@ -63,6 +63,7 @@
#include "virfile.h"
#include "command.h"
#include "virnetdev.h"
#include "virprocess.h"
#define VIR_FROM_THIS VIR_FROM_LXC

View File

@ -70,6 +70,7 @@
#include "processinfo.h"
#include "nodeinfo.h"
#include "virrandom.h"
#include "virprocess.h"
#include "rpc/virnetserver.h"
#define VIR_FROM_THIS VIR_FROM_LXC

View File

@ -44,6 +44,7 @@
#include "virfile.h"
#include "event.h"
#include "threads.h"
#include "virprocess.h"
#include "passfd.h"

View File

@ -40,6 +40,7 @@
#include "logging.h"
#include "virfile.h"
#include "virpidfile.h"
#include "virprocess.h"
#include "buf.h"
#define VIR_FROM_THIS VIR_FROM_NONE
@ -1686,31 +1687,6 @@ virCommandToString(virCommandPtr cmd)
}
/**
* virProcessTranslateStatus:
* @status: child exit status to translate
*
* Translate an exit status into a malloc'd string. Generic helper
* for virCommandRun(), virCommandWait(), virRun(), and virProcessWait()
* status argument, as well as raw waitpid().
*/
char *
virProcessTranslateStatus(int status)
{
char *buf;
if (WIFEXITED(status)) {
ignore_value(virAsprintf(&buf, _("exit status %d"),
WEXITSTATUS(status)));
} else if (WIFSIGNALED(status)) {
ignore_value(virAsprintf(&buf, _("fatal signal %d"),
WTERMSIG(status)));
} else {
ignore_value(virAsprintf(&buf, _("invalid value %d"), status));
}
return buf;
}
/*
* Manage input and output to the child process.
*/
@ -2256,55 +2232,6 @@ virCommandRunAsync(virCommandPtr cmd, pid_t *pid)
}
/**
* virProcessWait:
* @pid: child to wait on
* @exitstatus: optional status collection
*
* 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.
*/
int
virProcessWait(pid_t pid, int *exitstatus)
{
int ret;
int status;
if (pid <= 0) {
virReportSystemError(EINVAL, _("unable to wait for process %lld"),
(long long) pid);
return -1;
}
/* Wait for intermediate process to exit */
while ((ret = waitpid(pid, &status, 0)) == -1 &&
errno == EINTR);
if (ret == -1) {
virReportSystemError(errno, _("unable to wait for process %lld"),
(long long) pid);
return -1;
}
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 {
*exitstatus = status;
}
return 0;
}
/**
* virCommandWait:
* @cmd: command to wait on
@ -2369,67 +2296,6 @@ virCommandWait(virCommandPtr cmd, int *exitstatus)
#ifndef WIN32
/**
* virProcessAbort:
* @pid: child process to kill
*
* Abort a child process if PID is positive and that child is still
* running, without issuing any errors or affecting errno. Designed
* for error paths where some but not all paths to the cleanup code
* might have started the child process. If @pid is 0 or negative,
* this does nothing.
*/
void
virProcessAbort(pid_t pid)
{
int saved_errno;
int ret;
int status;
char *tmp = NULL;
if (pid <= 0)
return;
/* See if intermediate process has exited; if not, try a nice
* SIGTERM followed by a more severe SIGKILL.
*/
saved_errno = errno;
VIR_DEBUG("aborting child process %d", pid);
while ((ret = waitpid(pid, &status, WNOHANG)) == -1 &&
errno == EINTR);
if (ret == pid) {
tmp = virProcessTranslateStatus(status);
VIR_DEBUG("process has ended: %s", tmp);
goto cleanup;
} else if (ret == 0) {
VIR_DEBUG("trying SIGTERM to child process %d", pid);
kill(pid, SIGTERM);
usleep(10 * 1000);
while ((ret = waitpid(pid, &status, WNOHANG)) == -1 &&
errno == EINTR);
if (ret == pid) {
tmp = virProcessTranslateStatus(status);
VIR_DEBUG("process has ended: %s", tmp);
goto cleanup;
} else if (ret == 0) {
VIR_DEBUG("trying SIGKILL to child process %d", pid);
kill(pid, SIGKILL);
while ((ret = waitpid(pid, &status, 0)) == -1 &&
errno == EINTR);
if (ret == pid) {
tmp = virProcessTranslateStatus(status);
VIR_DEBUG("process has ended: %s", tmp);
goto cleanup;
}
}
}
VIR_DEBUG("failed to reap child %lld, abandoning it", (long long) pid);
cleanup:
VIR_FREE(tmp);
errno = saved_errno;
}
/**
* virCommandAbort:
* @cmd: command to abort
@ -2449,13 +2315,6 @@ virCommandAbort(virCommandPtr cmd)
cmd->reap = false;
}
#else /* WIN32 */
void
virProcessAbort(pid_t pid)
{
/* Not yet ported to mingw. Any volunteers? */
VIR_DEBUG("failed to reap child %lld, abandoning it", (long long)pid);
}
void
virCommandAbort(virCommandPtr cmd ATTRIBUTE_UNUSED)
{

View File

@ -140,9 +140,6 @@ void virCommandWriteArgLog(virCommandPtr cmd,
char *virCommandToString(virCommandPtr cmd) ATTRIBUTE_RETURN_CHECK;
char *virProcessTranslateStatus(int exitstatus) ATTRIBUTE_RETURN_CHECK;
int virCommandExec(virCommandPtr cmd) ATTRIBUTE_RETURN_CHECK;
int virCommandRun(virCommandPtr cmd,
@ -151,9 +148,6 @@ int virCommandRun(virCommandPtr cmd,
int virCommandRunAsync(virCommandPtr cmd,
pid_t *pid) ATTRIBUTE_RETURN_CHECK;
int virProcessWait(pid_t pid,
int *exitstatus) ATTRIBUTE_RETURN_CHECK;
int virCommandWait(virCommandPtr cmd,
int *exitstatus) ATTRIBUTE_RETURN_CHECK;
@ -165,8 +159,6 @@ int virCommandHandshakeWait(virCommandPtr cmd)
int virCommandHandshakeNotify(virCommandPtr cmd)
ATTRIBUTE_RETURN_CHECK;
void virProcessAbort(pid_t pid);
void virCommandAbort(virCommandPtr cmd);
void virCommandFree(virCommandPtr cmd);

View File

@ -87,6 +87,7 @@
#include "command.h"
#include "nonblocking.h"
#include "passfd.h"
#include "virprocess.h"
#ifndef NSIG
# define NSIG 32

View File

@ -24,8 +24,161 @@
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>
#include "virprocess.h"
#include "virterror_internal.h"
#include "memory.h"
#include "logging.h"
#include "util.h"
#define VIR_FROM_THIS VIR_FROM_NONE
/**
* virProcessTranslateStatus:
* @status: child exit status to translate
*
* Translate an exit status into a malloc'd string. Generic helper
* for virCommandRun(), virCommandWait(), virRun(), and virProcessWait()
* status argument, as well as raw waitpid().
*/
char *
virProcessTranslateStatus(int status)
{
char *buf;
if (WIFEXITED(status)) {
ignore_value(virAsprintf(&buf, _("exit status %d"),
WEXITSTATUS(status)));
} else if (WIFSIGNALED(status)) {
ignore_value(virAsprintf(&buf, _("fatal signal %d"),
WTERMSIG(status)));
} else {
ignore_value(virAsprintf(&buf, _("invalid value %d"), status));
}
return buf;
}
#ifndef WIN32
/**
* virProcessAbort:
* @pid: child process to kill
*
* Abort a child process if PID is positive and that child is still
* running, without issuing any errors or affecting errno. Designed
* for error paths where some but not all paths to the cleanup code
* might have started the child process. If @pid is 0 or negative,
* this does nothing.
*/
void
virProcessAbort(pid_t pid)
{
int saved_errno;
int ret;
int status;
char *tmp = NULL;
if (pid <= 0)
return;
/* See if intermediate process has exited; if not, try a nice
* SIGTERM followed by a more severe SIGKILL.
*/
saved_errno = errno;
VIR_DEBUG("aborting child process %d", pid);
while ((ret = waitpid(pid, &status, WNOHANG)) == -1 &&
errno == EINTR);
if (ret == pid) {
tmp = virProcessTranslateStatus(status);
VIR_DEBUG("process has ended: %s", tmp);
goto cleanup;
} else if (ret == 0) {
VIR_DEBUG("trying SIGTERM to child process %d", pid);
kill(pid, SIGTERM);
usleep(10 * 1000);
while ((ret = waitpid(pid, &status, WNOHANG)) == -1 &&
errno == EINTR);
if (ret == pid) {
tmp = virProcessTranslateStatus(status);
VIR_DEBUG("process has ended: %s", tmp);
goto cleanup;
} else if (ret == 0) {
VIR_DEBUG("trying SIGKILL to child process %d", pid);
kill(pid, SIGKILL);
while ((ret = waitpid(pid, &status, 0)) == -1 &&
errno == EINTR);
if (ret == pid) {
tmp = virProcessTranslateStatus(status);
VIR_DEBUG("process has ended: %s", tmp);
goto cleanup;
}
}
}
VIR_DEBUG("failed to reap child %lld, abandoning it", (long long) pid);
cleanup:
VIR_FREE(tmp);
errno = saved_errno;
}
#else
void
virProcessAbort(pid_t pid)
{
/* Not yet ported to mingw. Any volunteers? */
VIR_DEBUG("failed to reap child %lld, abandoning it", (long long)pid);
}
#endif
/**
* virProcessWait:
* @pid: child to wait on
* @exitstatus: optional status collection
*
* 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.
*/
int
virProcessWait(pid_t pid, int *exitstatus)
{
int ret;
int status;
if (pid <= 0) {
virReportSystemError(EINVAL, _("unable to wait for process %lld"),
(long long) pid);
return -1;
}
/* Wait for intermediate process to exit */
while ((ret = waitpid(pid, &status, 0)) == -1 &&
errno == EINTR);
if (ret == -1) {
virReportSystemError(errno, _("unable to wait for process %lld"),
(long long) pid);
return -1;
}
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 {
*exitstatus = status;
}
return 0;
}
/* send signal to a single process */
int virProcessKill(pid_t pid, int sig)

View File

@ -26,6 +26,17 @@
# include "internal.h"
char *
virProcessTranslateStatus(int status);
void
virProcessAbort(pid_t pid);
int
virProcessWait(pid_t pid, int *exitstatus)
ATTRIBUTE_RETURN_CHECK;
int virProcessKill(pid_t pid, int sig);
#endif /* __VIR_PROCESS_H__ */

View File

@ -48,6 +48,7 @@
#include "command.h"
#include "virrandom.h"
#include "dirname.h"
#include "virprocess.h"
#if TEST_OOM_TRACE
# include <execinfo.h>