mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +00:00
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:
parent
a5cf2ef4a7
commit
a05d4ca932
@ -36,6 +36,7 @@
|
||||
#include "virterror_internal.h"
|
||||
#include "virfile.h"
|
||||
#include "virpidfile.h"
|
||||
#include "virprocess.h"
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_QEMU
|
||||
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "virfile.h"
|
||||
#include "virtypedparam.h"
|
||||
#include "virdbus.h"
|
||||
#include "virprocess.h"
|
||||
#include "remote_protocol.h"
|
||||
#include "qemu_protocol.h"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include "virfile.h"
|
||||
#include "command.h"
|
||||
#include "virnetdev.h"
|
||||
#include "virprocess.h"
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_LXC
|
||||
|
||||
|
@ -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
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "virfile.h"
|
||||
#include "event.h"
|
||||
#include "threads.h"
|
||||
#include "virprocess.h"
|
||||
|
||||
#include "passfd.h"
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -87,6 +87,7 @@
|
||||
#include "command.h"
|
||||
#include "nonblocking.h"
|
||||
#include "passfd.h"
|
||||
#include "virprocess.h"
|
||||
|
||||
#ifndef NSIG
|
||||
# define NSIG 32
|
||||
|
@ -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)
|
||||
|
@ -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__ */
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "command.h"
|
||||
#include "virrandom.h"
|
||||
#include "dirname.h"
|
||||
#include "virprocess.h"
|
||||
|
||||
#if TEST_OOM_TRACE
|
||||
# include <execinfo.h>
|
||||
|
Loading…
Reference in New Issue
Block a user