From: "Daniel P. Berrange" <berrange(a)redhat.com>
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(a)redhat.com>
(cherry picked from commit 9467ab6074d02bd90248b5710b1c83856fefe9b4)
Signed-off-by: Eric Blake <eblake(a)redhat.com>
Conflicts:
src/lxc/lxc_controller.c
src/util/command.c
src/util/virprocess.c
tests/testutils.c
---
daemon/libvirtd.c | 1 +
daemon/remote.c | 1 +
po/POTFILES.in | 1 +
src/libvirt_private.syms | 7 ++-
src/lxc/lxc_container.c | 1 +
src/lxc/lxc_controller.c | 1 +
src/rpc/virnetsocket.c | 1 +
src/util/command.c | 143 +-----------------------------------------
src/util/command.h | 8 ---
src/util/util.c | 1 +
src/util/virprocess.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++
src/util/virprocess.h | 11 ++++
tests/testutils.c | 1 +
13 files changed, 181 insertions(+), 153 deletions(-)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index e9db433..49faece 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -36,6 +36,7 @@
#include "virterror_internal.h"
#include "virfile.h"
#include "virpidfile.h"
+#include "virprocess.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
diff --git a/daemon/remote.c b/daemon/remote.c
index 24553f0..435f663 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -46,6 +46,7 @@
#include "virfile.h"
#include "virtypedparam.h"
#include "virdbus.h"
+#include "virprocess.h"
#include "remote_protocol.h"
#include "qemu_protocol.h"
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4ea544b..7f1997c 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -141,6 +141,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
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 95f2543..f35fd63 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -140,12 +140,9 @@ virCommandSetPreExecHook;
virCommandSetWorkingDirectory;
virCommandToString;
virCommandTransferFD;
-virProcessTranslateStatus;
virCommandWait;
virCommandWriteArgLog;
virFork;
-virProcessAbort;
-virProcessWait;
virRun;
@@ -1454,7 +1451,11 @@ virPidFileDeletePath;
# virprocess.h
+virProcessAbort;
virProcessKill;
+virProcessTranslateStatus;
+virProcessWait;
+
# virrandom.h
virRandomBits;
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 442aa24..b0bd7a2 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -64,6 +64,7 @@
#include "virfile.h"
#include "command.h"
#include "virnetdev.h"
+#include "virprocess.h"
#define VIR_FROM_THIS VIR_FROM_LXC
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index b5cec3d..e6a2917 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -71,6 +71,7 @@
#include "command.h"
#include "processinfo.h"
#include "nodeinfo.h"
+#include "virprocess.h"
#define VIR_FROM_THIS VIR_FROM_LXC
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index 040090e..e82f375 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -43,6 +43,7 @@
#include "virfile.h"
#include "event.h"
#include "threads.h"
+#include "virprocess.h"
#include "passfd.h"
diff --git a/src/util/command.c b/src/util/command.c
index 02432fa..be10131 100644
--- a/src/util/command.c
+++ b/src/util/command.c
@@ -40,6 +40,7 @@
#include "logging.h"
#include "virfile.h"
#include "virpidfile.h"
+#include "virprocess.h"
#include "buf.h"
#include "ignore-value.h"
@@ -1647,31 +1648,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.
*/
@@ -2207,55 +2183,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);
- virCommandError(VIR_ERR_INTERNAL_ERROR,
- _("Child process (%lld) status unexpected: %s"),
- (long long) pid, NULLSTR(st));
- VIR_FREE(st);
- return -1;
- }
- } else {
- *exitstatus = status;
- }
-
- return 0;
-}
-
-/**
* virCommandWait:
* @cmd: command to wait on
* @exitstatus: optional status collection
@@ -2320,67 +2247,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
*
@@ -2400,13 +2266,6 @@ virCommandAbort(virCommandPtr cmd)
}
#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)
{
/* Mingw lacks WNOHANG and kill(). But since we haven't ported
diff --git a/src/util/command.h b/src/util/command.h
index 5cd85e5..cf4b041 100644
--- a/src/util/command.h
+++ b/src/util/command.h
@@ -137,9 +137,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,
@@ -148,9 +145,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;
@@ -162,8 +156,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);
diff --git a/src/util/util.c b/src/util/util.c
index b807c5a..1b32bcc 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -78,6 +78,7 @@
#include "command.h"
#include "nonblocking.h"
#include "passfd.h"
+#include "virprocess.h"
#ifndef NSIG
# define NSIG 32
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index e7db68f..ac78f1d 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -24,8 +24,165 @@
#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"
+#include "ignore-value.h"
+#define virReportError(code, ...) \
+ virReportErrorHelper(VIR_FROM_NONE, code, __FILE__, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
+
+#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)
diff --git a/src/util/virprocess.h b/src/util/virprocess.h
index b1000c6..048a73c 100644
--- a/src/util/virprocess.h
+++ b/src/util/virprocess.h
@@ -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__ */
diff --git a/tests/testutils.c b/tests/testutils.c
index 63bec52..2c38115 100644
--- a/tests/testutils.c
+++ b/tests/testutils.c
@@ -35,6 +35,7 @@
#include "logging.h"
#include "command.h"
#include "virrandom.h"
+#include "virprocess.h"
#if TEST_OOM_TRACE
# include <execinfo.h>
--
1.8.3.1