[Libguestfs] [PATCH 1/7] cmd: add a way to run (and wait) asynchronously commands

Pino Toscano ptoscano at redhat.com
Mon Feb 2 14:44:37 UTC 2015


---
 src/command.c          | 64 +++++++++++++++++++++++++++++++++++++++++++-------
 src/guestfs-internal.h |  3 +++
 2 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/src/command.c b/src/command.c
index 4bb469b..e26573d 100644
--- a/src/command.c
+++ b/src/command.c
@@ -360,7 +360,7 @@ debug_command (struct command *cmd)
 }
 
 static int
-run_command (struct command *cmd)
+run_command (struct command *cmd, bool get_stdout_fd, bool get_stderr_fd)
 {
   struct sigaction sa;
   int i, fd, max_fd, r;
@@ -368,8 +368,11 @@ run_command (struct command *cmd)
   int outfd[2] = { -1, -1 };
   char status_string[80];
 
+  get_stdout_fd = get_stdout_fd || cmd->stdout_callback != NULL;
+  get_stderr_fd = get_stderr_fd || cmd->capture_errors;
+
   /* Set up a pipe to capture command output and send it to the error log. */
-  if (cmd->capture_errors) {
+  if (get_stderr_fd) {
     if (pipe2 (errorfd, O_CLOEXEC) == -1) {
       perrorf (cmd->g, "pipe2");
       goto error;
@@ -377,7 +380,7 @@ run_command (struct command *cmd)
   }
 
   /* Set up a pipe to capture stdout for the callback. */
-  if (cmd->stdout_callback) {
+  if (get_stdout_fd) {
     if (pipe2 (outfd, O_CLOEXEC) == -1) {
       perrorf (cmd->g, "pipe2");
       goto error;
@@ -392,14 +395,14 @@ run_command (struct command *cmd)
 
   /* In parent, return to caller. */
   if (cmd->pid > 0) {
-    if (cmd->capture_errors) {
+    if (get_stderr_fd) {
       close (errorfd[1]);
       errorfd[1] = -1;
       cmd->errorfd = errorfd[0];
       errorfd[0] = -1;
     }
 
-    if (cmd->stdout_callback) {
+    if (get_stdout_fd) {
       close (outfd[1]);
       outfd[1] = -1;
       cmd->outfd = outfd[0];
@@ -410,15 +413,15 @@ run_command (struct command *cmd)
   }
 
   /* Child process. */
-  if (cmd->capture_errors) {
+  if (get_stderr_fd) {
     close (errorfd[0]);
-    if (!cmd->stdout_callback)
+    if (!get_stdout_fd)
       dup2 (errorfd[1], 1);
     dup2 (errorfd[1], 2);
     close (errorfd[1]);
   }
 
-  if (cmd->stdout_callback) {
+  if (get_stdout_fd) {
     close (outfd[0]);
     dup2 (outfd[1], 1);
     close (outfd[1]);
@@ -615,7 +618,7 @@ guestfs___cmd_run (struct command *cmd)
   if (cmd->g->verbose)
     debug_command (cmd);
 
-  if (run_command (cmd) == -1)
+  if (run_command (cmd, false, false) == -1)
     return -1;
 
   if (loop (cmd) == -1)
@@ -624,6 +627,49 @@ guestfs___cmd_run (struct command *cmd)
   return wait_command (cmd);
 }
 
+/* Fork, run the command, and returns the pid of the command,
+ * and its stdout and stderr file descriptors.
+ *
+ * Returns the exit status.  Test it using WIF* macros.
+ *
+ * On error: Calls error(g) and returns -1.
+ */
+int
+guestfs___cmd_run_async (struct command *cmd, pid_t *pid,
+                         int *stdout_fd, int *stderr_fd)
+{
+  finish_command (cmd);
+
+  if (cmd->g->verbose)
+    debug_command (cmd);
+
+  if (run_command (cmd, stdout_fd != NULL, stderr_fd != NULL) == -1)
+    return -1;
+
+  if (pid)
+    *pid = cmd->pid;
+  if (stdout_fd)
+    *stdout_fd = cmd->outfd;
+  if (stderr_fd)
+    *stderr_fd = cmd->errorfd;
+
+  return 0;
+}
+
+/* Wait for the command to finish.
+ *
+ * The command MUST have been started with guestfs___cmd_run_async.
+ *
+ * Returns the exit status.  Test it using WIF* macros.
+ *
+ * On error: Calls error(g) and returns -1.
+ */
+int
+guestfs___cmd_wait (struct command *cmd)
+{
+  return wait_command (cmd);
+}
+
 void
 guestfs___cmd_close (struct command *cmd)
 {
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 573c3da..bd5f675 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -20,6 +20,7 @@
 #define GUESTFS_INTERNAL_H_
 
 #include <stdbool.h>
+#include <sys/types.h>
 
 #include <libintl.h>
 
@@ -870,6 +871,8 @@ extern void guestfs___cmd_set_stderr_to_stdout (struct command *);
 extern void guestfs___cmd_clear_capture_errors (struct command *);
 extern void guestfs___cmd_clear_close_files (struct command *);
 extern int guestfs___cmd_run (struct command *);
+extern int guestfs___cmd_run_async (struct command *, pid_t *pid, int *stdout_fd, int *stderr_fd);
+extern int guestfs___cmd_wait (struct command *);
 extern void guestfs___cmd_close (struct command *);
 
 #ifdef HAVE_ATTRIBUTE_CLEANUP
-- 
1.9.3




More information about the Libguestfs mailing list