From: Johannes Sixt <johannes.sixt@telecom•at>
To: gitster@pobox•com
Cc: git@vger•kernel.org
Subject: [PATCH amend 08/14] Add infrastructure to run a function asynchronously.
Date: Sun, 14 Oct 2007 19:08:45 +0200 [thread overview]
Message-ID: <200710141908.45779.johannes.sixt@telecom.at> (raw)
In-Reply-To: <1192305984-22594-9-git-send-email-johannes.sixt@telecom.at>
This adds start_async() and finish_async(), which runs a function
asynchronously. Communication with the caller happens only via pipes.
For this reason, this implementation forks off a child process that runs
the function.
Signed-off-by: Johannes Sixt <johannes.sixt@telecom•at>
---
This is the same as submitted previously except it uses close_pair()
to close the pipe in an error patch and improves the comments in
run-command.h.
-- Hannes
run-command.c | 52 ++++++++++++++++++++++++++++++++++++++++++++--------
run-command.h | 22 ++++++++++++++++++++++
2 files changed, 66 insertions(+), 8 deletions(-)
diff --git a/run-command.c b/run-command.c
index d00c03b..db02f75 100644
--- a/run-command.c
+++ b/run-command.c
@@ -127,16 +127,11 @@ int start_command(struct child_process *cmd)
return 0;
}
-int finish_command(struct child_process *cmd)
+static int wait_or_whine(pid_t pid)
{
- if (cmd->close_in)
- close(cmd->in);
- if (cmd->close_out)
- close(cmd->out);
-
for (;;) {
int status, code;
- pid_t waiting = waitpid(cmd->pid, &status, 0);
+ pid_t waiting = waitpid(pid, &status, 0);
if (waiting < 0) {
if (errno == EINTR)
@@ -144,7 +139,7 @@ int finish_command(struct child_process *cmd)
error("waitpid failed (%s)", strerror(errno));
return -ERR_RUN_COMMAND_WAITPID;
}
- if (waiting != cmd->pid)
+ if (waiting != pid)
return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
if (WIFSIGNALED(status))
return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
@@ -158,6 +153,15 @@ int finish_command(struct child_process *cmd)
}
}
+int finish_command(struct child_process *cmd)
+{
+ if (cmd->close_in)
+ close(cmd->in);
+ if (cmd->close_out)
+ close(cmd->out);
+ return wait_or_whine(cmd->pid);
+}
+
int run_command(struct child_process *cmd)
{
int code = start_command(cmd);
@@ -200,3 +204,35 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const
cmd.env = env;
return run_command(&cmd);
}
+
+int start_async(struct async *async)
+{
+ int pipe_out[2];
+
+ if (pipe(pipe_out) < 0) {
+ return error("cannot create pipe: %s", strerror(errno));
+ }
+
+ async->pid = fork();
+ if (async->pid < 0) {
+ error("fork (async) failed: %s", strerror(errno));
+ close_pair(pipe_out);
+ return -1;
+ }
+ if (!async->pid) {
+ close(pipe_out[0]);
+ exit(!!async->proc(pipe_out[1], async->data));
+ }
+ async->out = pipe_out[0];
+ close(pipe_out[1]);
+ return 0;
+}
+
+int finish_async(struct async *async)
+{
+ int ret = 0;
+
+ if (wait_or_whine(async->pid))
+ ret = error("waitpid (async) failed");
+ return ret;
+}
diff --git a/run-command.h b/run-command.h
index 35b9fb6..94e1e9d 100644
--- a/run-command.h
+++ b/run-command.h
@@ -43,4 +43,26 @@ int run_command_v_opt_cd(const char **argv, int opt, const char *dir);
*/
int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env);
+/*
+ * The purpose of the following functions is to feed a pipe by running
+ * a function asynchronously and providing output that the caller reads.
+ *
+ * It is expected that no synchronization and mutual exclusion between
+ * the caller and the feed function is necessary so that the function
+ * can run in a thread without interfering with the caller.
+ */
+struct async {
+ /*
+ * proc writes to fd and closes it;
+ * returns 0 on success, non-zero on failure
+ */
+ int (*proc)(int fd, void *data);
+ void *data;
+ int out; /* caller reads from here and closes it */
+ pid_t pid;
+};
+
+int start_async(struct async *async);
+int finish_async(struct async *async);
+
#endif
--
1.5.3.2.141.g48f10
next prev parent reply other threads:[~2007-10-14 17:09 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-10-13 20:06 [PATCH 0/14] fork/exec removal series Johannes Sixt
2007-10-13 20:06 ` [PATCH 01/14] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt
2007-10-13 20:06 ` [PATCH 02/14] Use start_command() in git_connect() instead of explicit fork/exec Johannes Sixt
2007-10-13 20:06 ` [PATCH 03/14] Use start_command() to run content filters " Johannes Sixt
2007-10-13 20:06 ` [PATCH 04/14] Use run_command() to spawn external diff programs instead of fork/exec Johannes Sixt
2007-10-13 20:06 ` [PATCH 05/14] Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec Johannes Sixt
2007-10-13 20:06 ` [PATCH 06/14] Have start_command() create a pipe to read the stderr of the child Johannes Sixt
2007-10-13 20:06 ` [PATCH 07/14] upload-pack: Use start_command() to run pack-objects in create_pack_file() Johannes Sixt
2007-10-13 20:06 ` [PATCH 08/14] Add infrastructure to run a function asynchronously Johannes Sixt
2007-10-13 20:06 ` [PATCH 09/14] Use the asyncronous function infrastructure in builtin-fetch-pack.c Johannes Sixt
2007-10-13 20:06 ` [PATCH 10/14] upload-pack: Move the revision walker into a separate function Johannes Sixt
2007-10-13 20:06 ` [PATCH 11/14] upload-pack: Run rev-list in an asynchronous function Johannes Sixt
2007-10-13 20:06 ` [PATCH 12/14] t0021-conversion.sh: Test that the clean filter really cleans content Johannes Sixt
2007-10-13 20:06 ` [PATCH 13/14] Avoid a dup2(2) in apply_filter() - start_command() can do it for us Johannes Sixt
2007-10-13 20:06 ` [PATCH 14/14] Use the asyncronous function infrastructure to run the content filter Johannes Sixt
2007-10-14 3:07 ` Johannes Schindelin
2007-10-14 9:39 ` Johannes Sixt
2007-10-14 17:14 ` [PATCH amend " Johannes Sixt
2007-10-14 17:08 ` Johannes Sixt [this message]
2007-10-14 0:57 ` [PATCH 01/14] Change git_connect() to return a struct child_process instead of a pid_t Johannes Schindelin
2007-10-14 9:40 ` Johannes Sixt
2007-10-14 17:10 ` Johannes Schindelin
2007-10-14 2:11 ` [PATCH 0/14] fork/exec removal series Shawn O. Pearce
2007-10-14 2:50 ` Johannes Schindelin
2007-10-14 2:58 ` Shawn O. Pearce
2007-10-14 7:12 ` Pierre Habouzit
2007-10-14 7:17 ` Pierre Habouzit
2007-10-14 7:28 ` Pierre Habouzit
2007-10-14 9:10 ` Andreas Ericsson
2007-10-14 17:09 ` Johannes Schindelin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200710141908.45779.johannes.sixt@telecom.at \
--to=johannes.sixt@telecom$(echo .)at \
--cc=git@vger$(echo .)kernel.org \
--cc=gitster@pobox$(echo .)com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox