* [PATCH 0/5] fork/exec removal series @ 2007-09-30 20:09 Johannes Sixt 2007-09-30 20:09 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt ` (2 more replies) 0 siblings, 3 replies; 30+ messages in thread From: Johannes Sixt @ 2007-09-30 20:09 UTC (permalink / raw) To: gitster; +Cc: git, Johannes Sixt Here is a series of patches that removes a number fork/exec pairs. They are replaced by delegating to start_command/finish_command/run_command. You can regard this as the beginning of the MinGW port integration. There still remain a few forks, which fall into these categories: - They are in tools or code that are not (yet) ported to MinGW.[*] - The fork()s are not followed by exec(). These need a different implementation. I am thinking of a start_coroutine()/finish_coroutine() API that is implemented with threads in MinGW. (Suggestions of a better as well as implementations are welcome.) - The upload-pack case calls for an entirely different solution. [*] Just this weekend Mike Pape ported git-daemon, but I didn't find the time to have it integrated in this series - if that were possible at all. Patch 2 depends on Patch 1; otherwise, there are no dependencies. The series goes on top of next (it touches str_buf stuff in connect.c). builtin-archive.c | 8 +-- builtin-fetch-pack.c | 63 ++++++++----------------- cache.h | 4 +- connect.c | 126 ++++++++++++++++++++++++-------------------------- convert.c | 36 ++++---------- diff.c | 38 +-------------- peek-remote.c | 8 +-- send-pack.c | 8 +-- transport.c | 9 +--- 9 files changed, 106 insertions(+), 194 deletions(-) -- Hannes ^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t. 2007-09-30 20:09 [PATCH 0/5] fork/exec removal series Johannes Sixt @ 2007-09-30 20:09 ` Johannes Sixt 2007-09-30 20:09 ` [PATCH 2/5] Use start_command() in git_connect() instead of explicit fork/exec Johannes Sixt ` (2 more replies) 2007-09-30 20:20 ` [PATCH 0/5] fork/exec removal series Junio C Hamano 2007-09-30 21:14 ` Johannes Schindelin 2 siblings, 3 replies; 30+ messages in thread From: Johannes Sixt @ 2007-09-30 20:09 UTC (permalink / raw) To: gitster; +Cc: git, Johannes Sixt This prepares the API of git_connect() and finish_connect() to operate on a struct child_process. Currently, we just use that object as a placeholder for the pid that we used to return. A follow-up patch will change the implementation of git_connect() and finish_connect() to make full use of the object. Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> --- builtin-archive.c | 8 +++----- builtin-fetch-pack.c | 8 +++----- cache.h | 4 ++-- connect.c | 28 +++++++++++++++------------- peek-remote.c | 8 +++----- send-pack.c | 8 +++----- transport.c | 9 ++------- 7 files changed, 31 insertions(+), 42 deletions(-) diff --git a/builtin-archive.c b/builtin-archive.c index 04385de..76db6cf 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -30,7 +30,7 @@ static int run_remote_archiver(const char *remote, int argc, { char *url, buf[LARGE_PACKET_MAX]; int fd[2], i, len, rv; - pid_t pid; + struct child_process *chld; const char *exec = "git-upload-archive"; int exec_at = 0; @@ -46,9 +46,7 @@ static int run_remote_archiver(const char *remote, int argc, } url = xstrdup(remote); - pid = git_connect(fd, url, exec, 0); - if (pid < 0) - return pid; + chld = git_connect(fd, url, exec, 0); for (i = 1; i < argc; i++) { if (i == exec_at) @@ -76,7 +74,7 @@ static int run_remote_archiver(const char *remote, int argc, rv = recv_sideband("archive", fd[0], 1, 2); close(fd[0]); close(fd[1]); - rv |= finish_connect(pid); + rv |= finish_connect(chld); return !!rv; } diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 8f25d50..19c144d 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -762,7 +762,7 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args, { int i, ret; int fd[2]; - pid_t pid; + struct child_process *chld; struct ref *ref; struct stat st; @@ -773,16 +773,14 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args, st.st_mtime = 0; } - pid = git_connect(fd, (char *)dest, uploadpack, + chld = git_connect(fd, (char *)dest, uploadpack, args.verbose ? CONNECT_VERBOSE : 0); - if (pid < 0) - return NULL; if (heads && nr_heads) nr_heads = remove_duplicates(nr_heads, heads); ref = do_fetch_pack(fd, nr_heads, heads, pack_lockfile); close(fd[0]); close(fd[1]); - ret = finish_connect(pid); + ret = finish_connect(chld); if (!ret && nr_heads) { /* If the heads to pull were given, we should have diff --git a/cache.h b/cache.h index 27485d3..32ce8a7 100644 --- a/cache.h +++ b/cache.h @@ -503,8 +503,8 @@ struct ref { #define REF_TAGS (1u << 2) #define CONNECT_VERBOSE (1u << 0) -extern pid_t git_connect(int fd[2], char *url, const char *prog, int flags); -extern int finish_connect(pid_t pid); +extern struct child_process *git_connect(int fd[2], char *url, const char *prog, int flags); +extern int finish_connect(struct child_process *chld); extern int path_match(const char *path, int nr, char **match); extern int get_ack(int fd, unsigned char *result_sha1); extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags); diff --git a/connect.c b/connect.c index 3d5c4ab..f6dcab9 100644 --- a/connect.c +++ b/connect.c @@ -468,21 +468,22 @@ char *get_port(char *host) } /* - * This returns 0 if the transport protocol does not need fork(2), + * This returns NULL if the transport protocol does not need fork(2), * or a process id if it does. Once done, finish the connection * with finish_connect() with the value returned from this function - * (it is safe to call finish_connect() with 0 to support the former + * (it is safe to call finish_connect() with NULL to support the former * case). * - * Does not return a negative value on error; it just dies. + * If it returns, the connect is successful; it just dies on errors. */ -pid_t git_connect(int fd[2], char *url, const char *prog, int flags) +struct child_process *git_connect(int fd[2], char *url, + const char *prog, int flags) { char *host, *path = url; char *end; int c; int pipefd[2][2]; - pid_t pid; + struct child_process *chld; enum protocol protocol = PROTO_LOCAL; int free_path = 0; char *port = NULL; @@ -568,15 +569,16 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags) free(target_host); if (free_path) free(path); - return 0; + return NULL; } if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0) die("unable to create pipe pair for communication"); - pid = fork(); - if (pid < 0) + chld = xcalloc(1, sizeof(*chld)); + chld->pid = fork(); + if (chld->pid < 0) die("unable to fork"); - if (!pid) { + if (!chld->pid) { struct strbuf cmd; strbuf_init(&cmd, MAX_CMD_LEN); @@ -625,15 +627,15 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags) close(pipefd[1][0]); if (free_path) free(path); - return pid; + return chld; } -int finish_connect(pid_t pid) +int finish_connect(struct child_process *chld) { - if (pid == 0) + if (chld == NULL) return 0; - while (waitpid(pid, NULL, 0) < 0) { + while (waitpid(chld->pid, NULL, 0) < 0) { if (errno != EINTR) return -1; } diff --git a/peek-remote.c b/peek-remote.c index ceb7871..59cc8eb 100644 --- a/peek-remote.c +++ b/peek-remote.c @@ -25,7 +25,7 @@ int main(int argc, char **argv) int i, ret; char *dest = NULL; int fd[2]; - pid_t pid; + struct child_process *chld; int nongit = 0; unsigned flags = 0; @@ -64,12 +64,10 @@ int main(int argc, char **argv) if (!dest || i != argc - 1) usage(peek_remote_usage); - pid = git_connect(fd, dest, uploadpack, 0); - if (pid < 0) - return 1; + chld = git_connect(fd, dest, uploadpack, 0); ret = peek_remote(fd, flags); close(fd[0]); close(fd[1]); - ret |= finish_connect(pid); + ret |= finish_connect(chld); return !!ret; } diff --git a/send-pack.c b/send-pack.c index 4533d1b..e9257fd 100644 --- a/send-pack.c +++ b/send-pack.c @@ -362,7 +362,7 @@ int main(int argc, char **argv) char *dest = NULL; char **heads = NULL; int fd[2], ret; - pid_t pid; + struct child_process *chld; char *remote_name = NULL; struct remote *remote = NULL; @@ -426,12 +426,10 @@ int main(int argc, char **argv) } } - pid = git_connect(fd, dest, receivepack, verbose ? CONNECT_VERBOSE : 0); - if (pid < 0) - return 1; + chld = git_connect(fd, dest, receivepack, verbose ? CONNECT_VERBOSE : 0); ret = send_pack(fd[0], fd[1], remote, nr_heads, heads); close(fd[0]); close(fd[1]); - ret |= finish_connect(pid); + ret |= finish_connect(chld); return !!ret; } diff --git a/transport.c b/transport.c index 3475cca..54ed9bc 100644 --- a/transport.c +++ b/transport.c @@ -279,18 +279,13 @@ static struct ref *get_refs_via_connect(const struct transport *transport) struct git_transport_data *data = transport->data; struct ref *refs; int fd[2]; - pid_t pid; char *dest = xstrdup(transport->url); - - pid = git_connect(fd, dest, data->uploadpack, 0); - - if (pid < 0) - die("Failed to connect to \"%s\"", transport->url); + struct child_process *chld = git_connect(fd, dest, data->uploadpack, 0); get_remote_heads(fd[0], &refs, 0, NULL, 0); packet_flush(fd[1]); - finish_connect(pid); + finish_connect(chld); free(dest); -- 1.5.3.3.1134.gee562 ^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 2/5] Use start_command() in git_connect() instead of explicit fork/exec. 2007-09-30 20:09 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt @ 2007-09-30 20:09 ` Johannes Sixt 2007-09-30 20:09 ` [PATCH 3/5] Use start_command() to run the filter " Johannes Sixt 2007-09-30 20:43 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Junio C Hamano 2007-09-30 21:04 ` Johannes Schindelin 2 siblings, 1 reply; 30+ messages in thread From: Johannes Sixt @ 2007-09-30 20:09 UTC (permalink / raw) To: gitster; +Cc: git, Johannes Sixt The child process handling is delegated to start_command() and finish_command(). Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> --- connect.c | 104 ++++++++++++++++++++++++++++-------------------------------- 1 files changed, 49 insertions(+), 55 deletions(-) diff --git a/connect.c b/connect.c index f6dcab9..29fd431 100644 --- a/connect.c +++ b/connect.c @@ -482,11 +482,12 @@ struct child_process *git_connect(int fd[2], char *url, char *host, *path = url; char *end; int c; - int pipefd[2][2]; struct child_process *chld; enum protocol protocol = PROTO_LOCAL; int free_path = 0; char *port = NULL; + const char **arg; + struct strbuf cmd; /* Without this we cannot rely on waitpid() to tell * what happened to our children. @@ -572,72 +573,65 @@ struct child_process *git_connect(int fd[2], char *url, return NULL; } - if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0) - die("unable to create pipe pair for communication"); chld = xcalloc(1, sizeof(*chld)); - chld->pid = fork(); - if (chld->pid < 0) - die("unable to fork"); - if (!chld->pid) { - struct strbuf cmd; - - strbuf_init(&cmd, MAX_CMD_LEN); - strbuf_addstr(&cmd, prog); - strbuf_addch(&cmd, ' '); - sq_quote_buf(&cmd, path); - if (cmd.len >= MAX_CMD_LEN) - die("command line too long"); - - dup2(pipefd[1][0], 0); - dup2(pipefd[0][1], 1); - close(pipefd[0][0]); - close(pipefd[0][1]); - close(pipefd[1][0]); - close(pipefd[1][1]); - if (protocol == PROTO_SSH) { - const char *ssh, *ssh_basename; - ssh = getenv("GIT_SSH"); - if (!ssh) ssh = "ssh"; - ssh_basename = strrchr(ssh, '/'); - if (!ssh_basename) - ssh_basename = ssh; - else - ssh_basename++; - if (!port) - execlp(ssh, ssh_basename, host, cmd.buf, NULL); - else - execlp(ssh, ssh_basename, "-p", port, host, - cmd.buf, NULL); + strbuf_init(&cmd, MAX_CMD_LEN); + strbuf_addstr(&cmd, prog); + strbuf_addch(&cmd, ' '); + sq_quote_buf(&cmd, path); + if (cmd.len >= MAX_CMD_LEN) + die("command line too long"); + + chld->in = chld->out = -1; + chld->argv = arg = xcalloc(6, sizeof(*arg)); + if (protocol == PROTO_SSH) { + const char *ssh = getenv("GIT_SSH"); + if (!ssh) ssh = "ssh"; + + *arg++ = ssh; + if (port) { + *arg++ = "-p"; + *arg++ = port; } - else { - unsetenv(ALTERNATE_DB_ENVIRONMENT); - unsetenv(DB_ENVIRONMENT); - unsetenv(GIT_DIR_ENVIRONMENT); - unsetenv(GIT_WORK_TREE_ENVIRONMENT); - unsetenv(GRAFT_ENVIRONMENT); - unsetenv(INDEX_ENVIRONMENT); - execlp("sh", "sh", "-c", cmd.buf, NULL); - } - die("exec failed"); + *arg++ = host; + } + else { + /* remove these from the environment */ + const char *env[] = { + ALTERNATE_DB_ENVIRONMENT, + DB_ENVIRONMENT, + GIT_DIR_ENVIRONMENT, + GIT_WORK_TREE_ENVIRONMENT, + GRAFT_ENVIRONMENT, + INDEX_ENVIRONMENT, + NULL + }; + chld->env = env; + *arg++ = "sh"; + *arg++ = "-c"; } - fd[0] = pipefd[0][0]; - fd[1] = pipefd[1][1]; - close(pipefd[0][1]); - close(pipefd[1][0]); + *arg++ = cmd.buf; + *arg = NULL; + + if (start_command(chld)) + die("unable to fork"); + + fd[0] = chld->out; /* read from child's stdout */ + fd[1] = chld->in; /* write to child's stdin */ if (free_path) free(path); + strbuf_release(&cmd); return chld; } int finish_connect(struct child_process *chld) { + int code; if (chld == NULL) return 0; - while (waitpid(chld->pid, NULL, 0) < 0) { - if (errno != EINTR) - return -1; - } - return 0; + code = finish_command(chld); + free(chld->argv); + free(chld); + return code; } -- 1.5.3.3.1134.gee562 ^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 3/5] Use start_command() to run the filter instead of explicit fork/exec. 2007-09-30 20:09 ` [PATCH 2/5] Use start_command() in git_connect() instead of explicit fork/exec Johannes Sixt @ 2007-09-30 20:09 ` Johannes Sixt 2007-09-30 20:10 ` [PATCH 4/5] Use run_command() to spawn external diff programs instead of fork/exec Johannes Sixt 2007-09-30 21:07 ` [PATCH 3/5] Use start_command() to run the filter instead of explicit fork/exec Johannes Schindelin 0 siblings, 2 replies; 30+ messages in thread From: Johannes Sixt @ 2007-09-30 20:09 UTC (permalink / raw) To: gitster; +Cc: git, Johannes Sixt Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> --- convert.c | 36 ++++++++++-------------------------- 1 files changed, 10 insertions(+), 26 deletions(-) diff --git a/convert.c b/convert.c index 0d5e909..560679d 100644 --- a/convert.c +++ b/convert.c @@ -196,40 +196,24 @@ static int filter_buffer(const char *path, const char *src, /* * Spawn cmd and feed the buffer contents through its stdin. */ - struct child_process child_process; - int pipe_feed[2]; + struct child_process chld; int write_err, status; + const char *argv[] = { "sh", "-c", cmd, NULL }; - memset(&child_process, 0, sizeof(child_process)); + memset(&chld, 0, sizeof(chld)); + chld.argv = argv; + chld.in = -1; - if (pipe(pipe_feed) < 0) { - error("cannot create pipe to run external filter %s", cmd); - return 1; - } + if (start_command(&chld)) + return error("cannot fork to run external filter %s", cmd); - child_process.pid = fork(); - if (child_process.pid < 0) { - error("cannot fork to run external filter %s", cmd); - close(pipe_feed[0]); - close(pipe_feed[1]); - return 1; - } - if (!child_process.pid) { - dup2(pipe_feed[0], 0); - close(pipe_feed[0]); - close(pipe_feed[1]); - execlp("sh", "sh", "-c", cmd, NULL); - return 1; - } - close(pipe_feed[0]); - - write_err = (write_in_full(pipe_feed[1], src, size) < 0); - if (close(pipe_feed[1])) + write_err = (write_in_full(chld.in, src, size) < 0); + if (close(chld.in)) write_err = 1; if (write_err) error("cannot feed the input to external filter %s", cmd); - status = finish_command(&child_process); + status = finish_command(&chld); if (status) error("external filter %s failed %d", cmd, -status); return (write_err || status); -- 1.5.3.3.1134.gee562 ^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 4/5] Use run_command() to spawn external diff programs instead of fork/exec. 2007-09-30 20:09 ` [PATCH 3/5] Use start_command() to run the filter " Johannes Sixt @ 2007-09-30 20:10 ` Johannes Sixt 2007-09-30 20:10 ` [PATCH 5/5] Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec Johannes Sixt 2007-09-30 21:10 ` [PATCH 4/5] Use run_command() to spawn external diff programs instead of fork/exec Johannes Schindelin 2007-09-30 21:07 ` [PATCH 3/5] Use start_command() to run the filter instead of explicit fork/exec Johannes Schindelin 1 sibling, 2 replies; 30+ messages in thread From: Johannes Sixt @ 2007-09-30 20:10 UTC (permalink / raw) To: gitster; +Cc: git, Johannes Sixt Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> --- diff.c | 38 +++----------------------------------- 1 files changed, 3 insertions(+), 35 deletions(-) diff --git a/diff.c b/diff.c index 0bd7e24..29dfa82 100644 --- a/diff.c +++ b/diff.c @@ -9,6 +9,7 @@ #include "xdiff-interface.h" #include "color.h" #include "attr.h" +#include "run-command.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 @@ -1748,40 +1749,6 @@ static void remove_tempfile_on_signal(int signo) raise(signo); } -static int spawn_prog(const char *pgm, const char **arg) -{ - pid_t pid; - int status; - - fflush(NULL); - pid = fork(); - if (pid < 0) - die("unable to fork"); - if (!pid) { - execvp(pgm, (char *const*) arg); - exit(255); - } - - while (waitpid(pid, &status, 0) < 0) { - if (errno == EINTR) - continue; - return -1; - } - - /* Earlier we did not check the exit status because - * diff exits non-zero if files are different, and - * we are not interested in knowing that. It was a - * mistake which made it harder to quit a diff-* - * session that uses the git-apply-patch-script as - * the GIT_EXTERNAL_DIFF. A custom GIT_EXTERNAL_DIFF - * should also exit non-zero only when it wants to - * abort the entire diff-* session. - */ - if (WIFEXITED(status) && !WEXITSTATUS(status)) - return 0; - return -1; -} - /* An external diff command takes: * * diff-cmd name infile1 infile1-sha1 infile1-mode \ @@ -1834,7 +1801,8 @@ static void run_external_diff(const char *pgm, *arg++ = name; } *arg = NULL; - retval = spawn_prog(pgm, spawn_arg); + fflush(NULL); + retval = run_command_v_opt(spawn_arg, 0); remove_tempfile(); if (retval) { fprintf(stderr, "external diff died, stopping at %s.\n", name); -- 1.5.3.3.1134.gee562 ^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 5/5] Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec. 2007-09-30 20:10 ` [PATCH 4/5] Use run_command() to spawn external diff programs instead of fork/exec Johannes Sixt @ 2007-09-30 20:10 ` Johannes Sixt 2007-09-30 21:10 ` [PATCH 4/5] Use run_command() to spawn external diff programs instead of fork/exec Johannes Schindelin 1 sibling, 0 replies; 30+ messages in thread From: Johannes Sixt @ 2007-09-30 20:10 UTC (permalink / raw) To: gitster; +Cc: git, Johannes Sixt Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> --- builtin-fetch-pack.c | 55 ++++++++++++++----------------------------------- 1 files changed, 16 insertions(+), 39 deletions(-) diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 19c144d..d0eca2d 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -7,6 +7,7 @@ #include "pack.h" #include "sideband.h" #include "fetch-pack.h" +#include "run-command.h" static int transfer_unpack_limit = -1; static int fetch_unpack_limit = -1; @@ -499,11 +500,13 @@ static int get_pack(int xd[2], char **pack_lockfile) char hdr_arg[256]; const char **av; int do_keep = args.keep_pack; - int keep_pipe[2]; + struct child_process cmd; side_pid = setup_sideband(fd, xd); - av = argv; + memset(&cmd, 0, sizeof(cmd)); + cmd.argv = av = argv; + *hdr_arg = 0; if (!args.keep_pack && unpack_limit) { struct pack_header header; @@ -519,8 +522,8 @@ static int get_pack(int xd[2], char **pack_lockfile) } if (do_keep) { - if (pack_lockfile && pipe(keep_pipe)) - die("fetch-pack: pipe setup failure: %s", strerror(errno)); + if (pack_lockfile) + cmd.out = -1; *av++ = "index-pack"; *av++ = "--stdin"; if (!args.quiet && !args.no_progress) @@ -544,43 +547,17 @@ static int get_pack(int xd[2], char **pack_lockfile) *av++ = hdr_arg; *av++ = NULL; - pid = fork(); - if (pid < 0) + cmd.in = fd[0]; + cmd.git_cmd = 1; + if (start_command(&cmd)) die("fetch-pack: unable to fork off %s", argv[0]); - if (!pid) { - dup2(fd[0], 0); - if (do_keep && pack_lockfile) { - dup2(keep_pipe[1], 1); - close(keep_pipe[0]); - close(keep_pipe[1]); - } - close(fd[0]); - close(fd[1]); - execv_git_cmd(argv); - die("%s exec failed", argv[0]); - } - close(fd[0]); close(fd[1]); - if (do_keep && pack_lockfile) { - close(keep_pipe[1]); - *pack_lockfile = index_pack_lockfile(keep_pipe[0]); - close(keep_pipe[0]); - } - while (waitpid(pid, &status, 0) < 0) { - if (errno != EINTR) - die("waiting for %s: %s", argv[0], strerror(errno)); - } - if (WIFEXITED(status)) { - int code = WEXITSTATUS(status); - if (code) - die("%s died with error code %d", argv[0], code); - return 0; - } - if (WIFSIGNALED(status)) { - int sig = WTERMSIG(status); - die("%s died of signal %d", argv[0], sig); - } - die("%s died of unnatural causes %d", argv[0], status); + if (do_keep && pack_lockfile) + *pack_lockfile = index_pack_lockfile(cmd.out); + + if (finish_command(&cmd)) + die("%s failed", argv[0]); + return 0; } static struct ref *do_fetch_pack(int fd[2], -- 1.5.3.3.1134.gee562 ^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 4/5] Use run_command() to spawn external diff programs instead of fork/exec. 2007-09-30 20:10 ` [PATCH 4/5] Use run_command() to spawn external diff programs instead of fork/exec Johannes Sixt 2007-09-30 20:10 ` [PATCH 5/5] Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec Johannes Sixt @ 2007-09-30 21:10 ` Johannes Schindelin 1 sibling, 0 replies; 30+ messages in thread From: Johannes Schindelin @ 2007-09-30 21:10 UTC (permalink / raw) To: Johannes Sixt; +Cc: gitster, git Hi, On Sun, 30 Sep 2007, Johannes Sixt wrote: > diff.c | 38 +++----------------------------------- > 1 files changed, 3 insertions(+), 35 deletions(-) _Nice_! Ciao, Dscho ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 3/5] Use start_command() to run the filter instead of explicit fork/exec. 2007-09-30 20:09 ` [PATCH 3/5] Use start_command() to run the filter " Johannes Sixt 2007-09-30 20:10 ` [PATCH 4/5] Use run_command() to spawn external diff programs instead of fork/exec Johannes Sixt @ 2007-09-30 21:07 ` Johannes Schindelin 1 sibling, 0 replies; 30+ messages in thread From: Johannes Schindelin @ 2007-09-30 21:07 UTC (permalink / raw) To: Johannes Sixt; +Cc: gitster, git Hi, On Sun, 30 Sep 2007, Johannes Sixt wrote: > - struct child_process child_process; > + struct child_process chld; Why? This patch is less readable because of that rename. Ciao, Dscho ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t. 2007-09-30 20:09 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt 2007-09-30 20:09 ` [PATCH 2/5] Use start_command() in git_connect() instead of explicit fork/exec Johannes Sixt @ 2007-09-30 20:43 ` Junio C Hamano 2007-09-30 21:40 ` Johannes Sixt 2007-10-01 7:23 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt 2007-09-30 21:04 ` Johannes Schindelin 2 siblings, 2 replies; 30+ messages in thread From: Junio C Hamano @ 2007-09-30 20:43 UTC (permalink / raw) To: Johannes Sixt; +Cc: gitster, git Johannes Sixt <johannes.sixt@telecom.at> writes: > This prepares the API of git_connect() and finish_connect() to operate on > a struct child_process. Currently, we just use that object as a placeholder > for the pid that we used to return. A follow-up patch will change the > implementation of git_connect() and finish_connect() to make full use > of the object. Good description, except removal of checks for negative return of the calling sites raised my eyebrow and had me spend a few more minutes to review than necessary (see below). > diff --git a/builtin-archive.c b/builtin-archive.c > index 04385de..76db6cf 100644 > --- a/builtin-archive.c > +++ b/builtin-archive.c > @@ -30,7 +30,7 @@ static int run_remote_archiver(const char *remote, int argc, > { > char *url, buf[LARGE_PACKET_MAX]; > int fd[2], i, len, rv; > - pid_t pid; > + struct child_process *chld; Is "child" a reserved keyword or something that we need to avoid its use as an identifier? > const char *exec = "git-upload-archive"; > int exec_at = 0; > > @@ -46,9 +46,7 @@ static int run_remote_archiver(const char *remote, int argc, > } > > url = xstrdup(remote); > - pid = git_connect(fd, url, exec, 0); > - if (pid < 0) > - return pid; > + chld = git_connect(fd, url, exec, 0); > Interesting. This and other callers of git_connect() were prepared to see git_connect() to report errors with negative PID but the callee simply died --- so this change is not regressing by removing an early error return. It would be better to have something like this in the commit log message: Old code had early-return-on-error checks at the calling sites of git_connect(), but the callee simply died on errors without returning negative values. This patch removes such bogosity. > diff --git a/connect.c b/connect.c > index 3d5c4ab..f6dcab9 100644 > --- a/connect.c > +++ b/connect.c > @@ -468,21 +468,22 @@ char *get_port(char *host) > } > > /* > - * This returns 0 if the transport protocol does not need fork(2), > + * This returns NULL if the transport protocol does not need fork(2), > * or a process id if it does. Once done, finish the connection It does not return a process ID anymore, so this comment needs to be updated. Instead, you now return a struct child_process that is newly allocated, and needs to be deallocated somehow. At the end of finish_connect() might be a good place to do so. > * with finish_connect() with the value returned from this function > - * (it is safe to call finish_connect() with 0 to support the former > + * (it is safe to call finish_connect() with NULL to support the former > * case). > * > - * Does not return a negative value on error; it just dies. > + * If it returns, the connect is successful; it just dies on errors. > */ > -pid_t git_connect(int fd[2], char *url, const char *prog, int flags) > +struct child_process *git_connect(int fd[2], char *url, > + const char *prog, int flags) > { > ... > -int finish_connect(pid_t pid) > +int finish_connect(struct child_process *chld) > { > - if (pid == 0) > + if (chld == NULL) > return 0; > > - while (waitpid(pid, NULL, 0) < 0) { > + while (waitpid(chld->pid, NULL, 0) < 0) { > if (errno != EINTR) > return -1; > } But it seems you don't, leaking the struct. I see this is fixed in the next patch in the series, but it would be nicer to have the free from the very beginning. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t. 2007-09-30 20:43 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Junio C Hamano @ 2007-09-30 21:40 ` Johannes Sixt 2007-10-03 20:09 ` [PATCH 0/5, resend] fork/exec removal series Johannes Sixt 2007-10-01 7:23 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt 1 sibling, 1 reply; 30+ messages in thread From: Johannes Sixt @ 2007-09-30 21:40 UTC (permalink / raw) To: git; +Cc: Junio C Hamano On Sunday 30 September 2007 22:43, Junio C Hamano wrote: > Johannes Sixt <johannes.sixt@telecom.at> writes: > > + struct child_process *chld; > > Is "child" a reserved keyword or something that we need to avoid > its use as an identifier? Allow me to call it "conn": We are using this as a "connection object". Will integrate your and Dscho's suggestions and resend when the strbuf series appears in master. -- Hannes ^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 0/5, resend] fork/exec removal series 2007-09-30 21:40 ` Johannes Sixt @ 2007-10-03 20:09 ` Johannes Sixt 2007-10-03 20:09 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt 0 siblings, 1 reply; 30+ messages in thread From: Johannes Sixt @ 2007-10-03 20:09 UTC (permalink / raw) To: gitster; +Cc: git, Johannes Sixt Here is a series of patches that removes a number fork/exec pairs. They are replaced by delegating to start_command/finish_command/run_command. I've addressed all issues that were raised. However, concerning whether git_connect() shoud return NULL or not, I decided to stay with my earlier approach to return NULL for non-forking connections. Consequently, I had to remove all error checks because there is now no unique value that can indicate failure. The motivation is that the alternate approach (to always return non-NULL for any successful connection and NULL for failure) would benefit *only* libification; but *if* that ever happens, a major audit (and possibly) rewrite in the callers has to be done anyway because currently we are juggling, leaking, and double-closing file descriptors like mad - in error paths and normal paths. Patch 2 depends on Patch 1; otherwise, there are no dependencies. The series goes on top of 'master'. Note that 'next' has an additional call of git_connect() in the new transport.c. builtin-archive.c | 8 +-- cache.h | 4 +- connect.c | 128 +++++++++++++++++++++++++--------------------------- convert.c | 30 +++---------- diff.c | 38 +-------------- fetch-pack.c | 43 +++++------------ peek-remote.c | 8 +-- send-pack.c | 8 +-- 8 files changed, 96 insertions(+), 171 deletions(-) -- Hannes ^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t. 2007-10-03 20:09 ` [PATCH 0/5, resend] fork/exec removal series Johannes Sixt @ 2007-10-03 20:09 ` Johannes Sixt 2007-10-03 20:09 ` [PATCH 2/5] Use start_command() in git_connect() instead of explicit fork/exec Johannes Sixt 0 siblings, 1 reply; 30+ messages in thread From: Johannes Sixt @ 2007-10-03 20:09 UTC (permalink / raw) To: gitster; +Cc: git, Johannes Sixt This prepares the API of git_connect() and finish_connect() to operate on a struct child_process. Currently, we just use that object as a placeholder for the pid that we used to return. A follow-up patch will change the implementation of git_connect() and finish_connect() to make full use of the object. Old code had early-return-on-error checks at the calling sites of git_connect(), but since git_connect() dies on errors anyway, these checks were removed. Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> --- I don't replace the waitpid() in finish_connect() by finish_command() because (1) that's not the purpose of this patch and (2) there is no corresponding start_command(), yet. -- Hannes builtin-archive.c | 8 +++----- cache.h | 4 ++-- connect.c | 31 +++++++++++++++++-------------- fetch-pack.c | 8 +++----- peek-remote.c | 8 +++----- send-pack.c | 8 +++----- 6 files changed, 31 insertions(+), 36 deletions(-) diff --git a/builtin-archive.c b/builtin-archive.c index 04385de..76f8d3d 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -30,7 +30,7 @@ static int run_remote_archiver(const char *remote, int argc, { char *url, buf[LARGE_PACKET_MAX]; int fd[2], i, len, rv; - pid_t pid; + struct child_process *conn; const char *exec = "git-upload-archive"; int exec_at = 0; @@ -46,9 +46,7 @@ static int run_remote_archiver(const char *remote, int argc, } url = xstrdup(remote); - pid = git_connect(fd, url, exec, 0); - if (pid < 0) - return pid; + conn = git_connect(fd, url, exec, 0); for (i = 1; i < argc; i++) { if (i == exec_at) @@ -76,7 +74,7 @@ static int run_remote_archiver(const char *remote, int argc, rv = recv_sideband("archive", fd[0], 1, 2); close(fd[0]); close(fd[1]); - rv |= finish_connect(pid); + rv |= finish_connect(conn); return !!rv; } diff --git a/cache.h b/cache.h index e0abcd6..548fb52 100644 --- a/cache.h +++ b/cache.h @@ -502,8 +502,8 @@ struct ref { #define REF_TAGS (1u << 2) #define CONNECT_VERBOSE (1u << 0) -extern pid_t git_connect(int fd[2], char *url, const char *prog, int flags); -extern int finish_connect(pid_t pid); +extern struct child_process *git_connect(int fd[2], char *url, const char *prog, int flags); +extern int finish_connect(struct child_process *conn); extern int path_match(const char *path, int nr, char **match); extern int get_ack(int fd, unsigned char *result_sha1); extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags); diff --git a/connect.c b/connect.c index 06d279e..458a502 100644 --- a/connect.c +++ b/connect.c @@ -468,21 +468,22 @@ char *get_port(char *host) } /* - * This returns 0 if the transport protocol does not need fork(2), - * or a process id if it does. Once done, finish the connection + * This returns NULL if the transport protocol does not need fork(2), or a + * struct child_process object if it does. Once done, finish the connection * with finish_connect() with the value returned from this function - * (it is safe to call finish_connect() with 0 to support the former + * (it is safe to call finish_connect() with NULL to support the former * case). * - * Does not return a negative value on error; it just dies. + * If it returns, the connect is successful; it just dies on errors. */ -pid_t git_connect(int fd[2], char *url, const char *prog, int flags) +struct child_process *git_connect(int fd[2], char *url, + const char *prog, int flags) { char *host, *path = url; char *end; int c; int pipefd[2][2]; - pid_t pid; + struct child_process *conn; enum protocol protocol = PROTO_LOCAL; int free_path = 0; char *port = NULL; @@ -568,15 +569,16 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags) free(target_host); if (free_path) free(path); - return 0; + return NULL; } if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0) die("unable to create pipe pair for communication"); - pid = fork(); - if (pid < 0) + conn = xcalloc(1, sizeof(*conn)); + conn->pid = fork(); + if (conn->pid < 0) die("unable to fork"); - if (!pid) { + if (!conn->pid) { struct strbuf cmd; strbuf_init(&cmd, MAX_CMD_LEN); @@ -625,17 +627,18 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags) close(pipefd[1][0]); if (free_path) free(path); - return pid; + return conn; } -int finish_connect(pid_t pid) +int finish_connect(struct child_process *conn) { - if (pid == 0) + if (conn == NULL) return 0; - while (waitpid(pid, NULL, 0) < 0) { + while (waitpid(conn->pid, NULL, 0) < 0) { if (errno != EINTR) return -1; } + free(conn); return 0; } diff --git a/fetch-pack.c b/fetch-pack.c index 9c81305..d06b5ec 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -668,7 +668,7 @@ int main(int argc, char **argv) int i, ret, nr_heads; char *dest = NULL, **heads; int fd[2]; - pid_t pid; + struct child_process *conn; struct stat st; setup_git_directory(); @@ -733,15 +733,13 @@ int main(int argc, char **argv) } if (!dest) usage(fetch_pack_usage); - pid = git_connect(fd, dest, uploadpack, verbose ? CONNECT_VERBOSE : 0); - if (pid < 0) - return 1; + conn = git_connect(fd, dest, uploadpack, verbose ? CONNECT_VERBOSE : 0); if (heads && nr_heads) nr_heads = remove_duplicates(nr_heads, heads); ret = fetch_pack(fd, nr_heads, heads); close(fd[0]); close(fd[1]); - ret |= finish_connect(pid); + ret |= finish_connect(conn); if (!ret && nr_heads) { /* If the heads to pull were given, we should have diff --git a/peek-remote.c b/peek-remote.c index ceb7871..8d20f7c 100644 --- a/peek-remote.c +++ b/peek-remote.c @@ -25,7 +25,7 @@ int main(int argc, char **argv) int i, ret; char *dest = NULL; int fd[2]; - pid_t pid; + struct child_process *conn; int nongit = 0; unsigned flags = 0; @@ -64,12 +64,10 @@ int main(int argc, char **argv) if (!dest || i != argc - 1) usage(peek_remote_usage); - pid = git_connect(fd, dest, uploadpack, 0); - if (pid < 0) - return 1; + conn = git_connect(fd, dest, uploadpack, 0); ret = peek_remote(fd, flags); close(fd[0]); close(fd[1]); - ret |= finish_connect(pid); + ret |= finish_connect(conn); return !!ret; } diff --git a/send-pack.c b/send-pack.c index f74e66a..f4c7bbf 100644 --- a/send-pack.c +++ b/send-pack.c @@ -362,7 +362,7 @@ int main(int argc, char **argv) char *dest = NULL; char **heads = NULL; int fd[2], ret; - pid_t pid; + struct child_process *conn; char *remote_name = NULL; struct remote *remote = NULL; @@ -426,12 +426,10 @@ int main(int argc, char **argv) } } - pid = git_connect(fd, dest, receivepack, verbose ? CONNECT_VERBOSE : 0); - if (pid < 0) - return 1; + conn = git_connect(fd, dest, receivepack, verbose ? CONNECT_VERBOSE : 0); ret = send_pack(fd[0], fd[1], remote, nr_heads, heads); close(fd[0]); close(fd[1]); - ret |= finish_connect(pid); + ret |= finish_connect(conn); return !!ret; } -- 1.5.3.3.1134.gee562 ^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 2/5] Use start_command() in git_connect() instead of explicit fork/exec. 2007-10-03 20:09 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt @ 2007-10-03 20:09 ` Johannes Sixt 2007-10-03 20:09 ` [PATCH 3/5] Use start_command() to run the filter " Johannes Sixt 0 siblings, 1 reply; 30+ messages in thread From: Johannes Sixt @ 2007-10-03 20:09 UTC (permalink / raw) To: gitster; +Cc: git, Johannes Sixt The child process handling is delegated to start_command() and finish_command(). Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> --- connect.c | 103 ++++++++++++++++++++++++++++-------------------------------- 1 files changed, 48 insertions(+), 55 deletions(-) diff --git a/connect.c b/connect.c index 458a502..bb55d19 100644 --- a/connect.c +++ b/connect.c @@ -482,11 +482,12 @@ struct child_process *git_connect(int fd[2], char *url, char *host, *path = url; char *end; int c; - int pipefd[2][2]; struct child_process *conn; enum protocol protocol = PROTO_LOCAL; int free_path = 0; char *port = NULL; + const char **arg; + struct strbuf cmd; /* Without this we cannot rely on waitpid() to tell * what happened to our children. @@ -572,73 +573,65 @@ struct child_process *git_connect(int fd[2], char *url, return NULL; } - if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0) - die("unable to create pipe pair for communication"); conn = xcalloc(1, sizeof(*conn)); - conn->pid = fork(); - if (conn->pid < 0) - die("unable to fork"); - if (!conn->pid) { - struct strbuf cmd; - - strbuf_init(&cmd, MAX_CMD_LEN); - strbuf_addstr(&cmd, prog); - strbuf_addch(&cmd, ' '); - sq_quote_buf(&cmd, path); - if (cmd.len >= MAX_CMD_LEN) - die("command line too long"); - - dup2(pipefd[1][0], 0); - dup2(pipefd[0][1], 1); - close(pipefd[0][0]); - close(pipefd[0][1]); - close(pipefd[1][0]); - close(pipefd[1][1]); - if (protocol == PROTO_SSH) { - const char *ssh, *ssh_basename; - ssh = getenv("GIT_SSH"); - if (!ssh) ssh = "ssh"; - ssh_basename = strrchr(ssh, '/'); - if (!ssh_basename) - ssh_basename = ssh; - else - ssh_basename++; - if (!port) - execlp(ssh, ssh_basename, host, cmd.buf, NULL); - else - execlp(ssh, ssh_basename, "-p", port, host, - cmd.buf, NULL); + strbuf_init(&cmd, MAX_CMD_LEN); + strbuf_addstr(&cmd, prog); + strbuf_addch(&cmd, ' '); + sq_quote_buf(&cmd, path); + if (cmd.len >= MAX_CMD_LEN) + die("command line too long"); + + conn->in = conn->out = -1; + conn->argv = arg = xcalloc(6, sizeof(*arg)); + if (protocol == PROTO_SSH) { + const char *ssh = getenv("GIT_SSH"); + if (!ssh) ssh = "ssh"; + + *arg++ = ssh; + if (port) { + *arg++ = "-p"; + *arg++ = port; } - else { - unsetenv(ALTERNATE_DB_ENVIRONMENT); - unsetenv(DB_ENVIRONMENT); - unsetenv(GIT_DIR_ENVIRONMENT); - unsetenv(GIT_WORK_TREE_ENVIRONMENT); - unsetenv(GRAFT_ENVIRONMENT); - unsetenv(INDEX_ENVIRONMENT); - execlp("sh", "sh", "-c", cmd.buf, NULL); - } - die("exec failed"); + *arg++ = host; + } + else { + /* remove these from the environment */ + const char *env[] = { + ALTERNATE_DB_ENVIRONMENT, + DB_ENVIRONMENT, + GIT_DIR_ENVIRONMENT, + GIT_WORK_TREE_ENVIRONMENT, + GRAFT_ENVIRONMENT, + INDEX_ENVIRONMENT, + NULL + }; + conn->env = env; + *arg++ = "sh"; + *arg++ = "-c"; } - fd[0] = pipefd[0][0]; - fd[1] = pipefd[1][1]; - close(pipefd[0][1]); - close(pipefd[1][0]); + *arg++ = cmd.buf; + *arg = NULL; + + if (start_command(conn)) + die("unable to fork"); + + fd[0] = conn->out; /* read from child's stdout */ + fd[1] = conn->in; /* write to child's stdin */ if (free_path) free(path); + strbuf_release(&cmd); return conn; } int finish_connect(struct child_process *conn) { + int code; if (conn == NULL) return 0; - while (waitpid(conn->pid, NULL, 0) < 0) { - if (errno != EINTR) - return -1; - } + code = finish_command(conn); + free(conn->argv); free(conn); - return 0; + return code; } -- 1.5.3.3.1134.gee562 ^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 3/5] Use start_command() to run the filter instead of explicit fork/exec. 2007-10-03 20:09 ` [PATCH 2/5] Use start_command() in git_connect() instead of explicit fork/exec Johannes Sixt @ 2007-10-03 20:09 ` Johannes Sixt 2007-10-03 20:09 ` [PATCH 4/5] Use run_command() to spawn external diff programs instead of fork/exec Johannes Sixt 0 siblings, 1 reply; 30+ messages in thread From: Johannes Sixt @ 2007-10-03 20:09 UTC (permalink / raw) To: gitster; +Cc: git, Johannes Sixt Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> --- convert.c | 30 +++++++----------------------- 1 files changed, 7 insertions(+), 23 deletions(-) diff --git a/convert.c b/convert.c index 0d5e909..6a8c806 100644 --- a/convert.c +++ b/convert.c @@ -197,34 +197,18 @@ static int filter_buffer(const char *path, const char *src, * Spawn cmd and feed the buffer contents through its stdin. */ struct child_process child_process; - int pipe_feed[2]; int write_err, status; + const char *argv[] = { "sh", "-c", cmd, NULL }; memset(&child_process, 0, sizeof(child_process)); + child_process.argv = argv; + child_process.in = -1; - if (pipe(pipe_feed) < 0) { - error("cannot create pipe to run external filter %s", cmd); - return 1; - } - - child_process.pid = fork(); - if (child_process.pid < 0) { - error("cannot fork to run external filter %s", cmd); - close(pipe_feed[0]); - close(pipe_feed[1]); - return 1; - } - if (!child_process.pid) { - dup2(pipe_feed[0], 0); - close(pipe_feed[0]); - close(pipe_feed[1]); - execlp("sh", "sh", "-c", cmd, NULL); - return 1; - } - close(pipe_feed[0]); + if (start_command(&child_process)) + return error("cannot fork to run external filter %s", cmd); - write_err = (write_in_full(pipe_feed[1], src, size) < 0); - if (close(pipe_feed[1])) + write_err = (write_in_full(child_process.in, src, size) < 0); + if (close(child_process.in)) write_err = 1; if (write_err) error("cannot feed the input to external filter %s", cmd); -- 1.5.3.3.1134.gee562 ^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 4/5] Use run_command() to spawn external diff programs instead of fork/exec. 2007-10-03 20:09 ` [PATCH 3/5] Use start_command() to run the filter " Johannes Sixt @ 2007-10-03 20:09 ` Johannes Sixt 2007-10-03 20:09 ` [PATCH 5/5] Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec Johannes Sixt 0 siblings, 1 reply; 30+ messages in thread From: Johannes Sixt @ 2007-10-03 20:09 UTC (permalink / raw) To: gitster; +Cc: git, Johannes Sixt Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> --- diff.c | 38 +++----------------------------------- 1 files changed, 3 insertions(+), 35 deletions(-) diff --git a/diff.c b/diff.c index 6648e01..30b7544 100644 --- a/diff.c +++ b/diff.c @@ -9,6 +9,7 @@ #include "xdiff-interface.h" #include "color.h" #include "attr.h" +#include "run-command.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 @@ -1748,40 +1749,6 @@ static void remove_tempfile_on_signal(int signo) raise(signo); } -static int spawn_prog(const char *pgm, const char **arg) -{ - pid_t pid; - int status; - - fflush(NULL); - pid = fork(); - if (pid < 0) - die("unable to fork"); - if (!pid) { - execvp(pgm, (char *const*) arg); - exit(255); - } - - while (waitpid(pid, &status, 0) < 0) { - if (errno == EINTR) - continue; - return -1; - } - - /* Earlier we did not check the exit status because - * diff exits non-zero if files are different, and - * we are not interested in knowing that. It was a - * mistake which made it harder to quit a diff-* - * session that uses the git-apply-patch-script as - * the GIT_EXTERNAL_DIFF. A custom GIT_EXTERNAL_DIFF - * should also exit non-zero only when it wants to - * abort the entire diff-* session. - */ - if (WIFEXITED(status) && !WEXITSTATUS(status)) - return 0; - return -1; -} - /* An external diff command takes: * * diff-cmd name infile1 infile1-sha1 infile1-mode \ @@ -1834,7 +1801,8 @@ static void run_external_diff(const char *pgm, *arg++ = name; } *arg = NULL; - retval = spawn_prog(pgm, spawn_arg); + fflush(NULL); + retval = run_command_v_opt(spawn_arg, 0); remove_tempfile(); if (retval) { fprintf(stderr, "external diff died, stopping at %s.\n", name); -- 1.5.3.3.1134.gee562 ^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 5/5] Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec. 2007-10-03 20:09 ` [PATCH 4/5] Use run_command() to spawn external diff programs instead of fork/exec Johannes Sixt @ 2007-10-03 20:09 ` Johannes Sixt 2007-10-04 8:55 ` Junio C Hamano 0 siblings, 1 reply; 30+ messages in thread From: Johannes Sixt @ 2007-10-03 20:09 UTC (permalink / raw) To: gitster; +Cc: git, Johannes Sixt Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> --- fetch-pack.c | 35 ++++++++++------------------------- 1 files changed, 10 insertions(+), 25 deletions(-) diff --git a/fetch-pack.c b/fetch-pack.c index d06b5ec..80268e1 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -6,6 +6,7 @@ #include "exec_cmd.h" #include "pack.h" #include "sideband.h" +#include "run-command.h" static int keep_pack; static int transfer_unpack_limit = -1; @@ -502,9 +503,12 @@ static int get_pack(int xd[2]) char hdr_arg[256]; const char **av; int do_keep = keep_pack; + struct child_process cmd; side_pid = setup_sideband(fd, xd); + memset(&cmd, 0, sizeof(cmd)); + cmd.argv = argv; av = argv; *hdr_arg = 0; if (unpack_limit) { @@ -544,33 +548,14 @@ static int get_pack(int xd[2]) *av++ = hdr_arg; *av++ = NULL; - pid = fork(); - if (pid < 0) + cmd.in = fd[0]; + cmd.git_cmd = 1; + if (start_command(&cmd)) die("fetch-pack: unable to fork off %s", argv[0]); - if (!pid) { - dup2(fd[0], 0); - close(fd[0]); - close(fd[1]); - execv_git_cmd(argv); - die("%s exec failed", argv[0]); - } - close(fd[0]); close(fd[1]); - while (waitpid(pid, &status, 0) < 0) { - if (errno != EINTR) - die("waiting for %s: %s", argv[0], strerror(errno)); - } - if (WIFEXITED(status)) { - int code = WEXITSTATUS(status); - if (code) - die("%s died with error code %d", argv[0], code); - return 0; - } - if (WIFSIGNALED(status)) { - int sig = WTERMSIG(status); - die("%s died of signal %d", argv[0], sig); - } - die("%s died of unnatural causes %d", argv[0], status); + if (finish_command(&cmd)) + die("%s failed", argv[0]); + return 0; } static int fetch_pack(int fd[2], int nr_match, char **match) -- 1.5.3.3.1134.gee562 ^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 5/5] Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec. 2007-10-03 20:09 ` [PATCH 5/5] Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec Johannes Sixt @ 2007-10-04 8:55 ` Junio C Hamano 2007-10-04 9:22 ` Johannes Sixt 0 siblings, 1 reply; 30+ messages in thread From: Junio C Hamano @ 2007-10-04 8:55 UTC (permalink / raw) To: Johannes Sixt; +Cc: git Johannes Sixt <johannes.sixt@telecom.at> writes: > Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> > --- > fetch-pack.c | 35 ++++++++++------------------------- > 1 files changed, 10 insertions(+), 25 deletions(-) > > diff --git a/fetch-pack.c b/fetch-pack.c > index d06b5ec..80268e1 100644 > --- a/fetch-pack.c > +++ b/fetch-pack.c > @@ -502,9 +503,12 @@ static int get_pack(int xd[2]) > char hdr_arg[256]; > const char **av; > int do_keep = keep_pack; > + struct child_process cmd; > > side_pid = setup_sideband(fd, xd); > > + memset(&cmd, 0, sizeof(cmd)); > + cmd.argv = argv; > av = argv; > *hdr_arg = 0; > if (unpack_limit) { Your patch to this function makes status and pid unused variables, which I've fixed up locally. The tip of your topic is currently queued to the tip of 'pu'; there were quite severe merge conflicts (textual conflicts in builtin-fetch-pack.c, and adjustment to transport.c for semantics change was also needed), so I ended up doing an evil merge there, which I am not very happy about. I suspect the evil-merge's changes to builtin-fetch-pack to handle the connection to the index-pack process may be quite busted, but I ran out of time. Please check if the result makes sense, Ok? I think Daniel and Shawn's git-fetch-in-C should graduate 'master' before this series. If you can re-send the series rebased on 2b5a06edca8f7237aad6464b349b79772024d2a2 (Restore default verbosity for http fetches.), it would be much appreciated. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 5/5] Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec. 2007-10-04 8:55 ` Junio C Hamano @ 2007-10-04 9:22 ` Johannes Sixt 2007-10-04 20:11 ` Johannes Sixt 0 siblings, 1 reply; 30+ messages in thread From: Johannes Sixt @ 2007-10-04 9:22 UTC (permalink / raw) To: Junio C Hamano; +Cc: Johannes Sixt, git Junio C Hamano schrieb: > I think Daniel and Shawn's git-fetch-in-C should graduate > 'master' before this series. If you can re-send the series > rebased on 2b5a06edca8f7237aad6464b349b79772024d2a2 (Restore > default verbosity for http fetches.), it would be much > appreciated. Sure, will do this evening. -- Hannes ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 5/5] Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec. 2007-10-04 9:22 ` Johannes Sixt @ 2007-10-04 20:11 ` Johannes Sixt 0 siblings, 0 replies; 30+ messages in thread From: Johannes Sixt @ 2007-10-04 20:11 UTC (permalink / raw) To: git; +Cc: Johannes Sixt, Junio C Hamano On Thursday 04 October 2007 11:22, Johannes Sixt wrote: > Junio C Hamano schrieb: > > I think Daniel and Shawn's git-fetch-in-C should graduate > > 'master' before this series. If you can re-send the series > > rebased on 2b5a06edca8f7237aad6464b349b79772024d2a2 (Restore > > default verbosity for http fetches.), it would be much > > appreciated. > > Sure, will do this evening. I've difficulties with this rebase: 2b5a06 does not compile for me due to 7155b727c9 (Introduce remove_dir_recursively()), which needs strbuf, but that is not merged into this branch. I can rebase on its parent (bundle transport: fix an alloc_ref() call) or 17df81ff (Merge branch 'db/fetch-pack' into next). I'd prefer the latter since it also has strbuf. -- Hannes ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t. 2007-09-30 20:43 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Junio C Hamano 2007-09-30 21:40 ` Johannes Sixt @ 2007-10-01 7:23 ` Johannes Sixt 2007-10-01 8:39 ` Junio C Hamano 1 sibling, 1 reply; 30+ messages in thread From: Johannes Sixt @ 2007-10-01 7:23 UTC (permalink / raw) To: Junio C Hamano; +Cc: Johannes Sixt, git Junio C Hamano schrieb: > Johannes Sixt <johannes.sixt@telecom.at> writes: > >> This prepares the API of git_connect() and finish_connect() to operate on >> a struct child_process. Currently, we just use that object as a placeholder >> for the pid that we used to return. A follow-up patch will change the >> implementation of git_connect() and finish_connect() to make full use >> of the object. > > Good description, except removal of checks for negative return > of the calling sites raised my eyebrow and had me spend a few > more minutes to review than necessary (see below). I've thought about this issue a bit more. Letting git_connect() die on error unconditionally is poison for any libification efforts. So here's a plan: 1. Let git_connect() return a struct child_process even for the non-forking case. This way a return value of NULL can uniquely identify a failure. 2. Keep the error checks in the callers (adjust to test for NULL). 3. Change the die() calls to return failure. 4. Note that the int fd[2] parameter to git_connect() is really an output: Remove it and use .in and .out of the returned struct child_process instead. And maybe: 5. Reuse somehow the struct child_process that git_proxy_connect() already fills in. Since my patch doesn't do (1), it can't do (2), i.e. keep the error checks - they must be removed because no unique failure value exists. So I could complete (1) in a new version of this patch, in order to also do (2). What is your preference? -- Hannes PS: I've postponed the completion of this plan - in favor of the MinGW port integration - because it only helps libification. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t. 2007-10-01 7:23 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt @ 2007-10-01 8:39 ` Junio C Hamano 2007-10-01 9:08 ` Johannes Sixt 0 siblings, 1 reply; 30+ messages in thread From: Junio C Hamano @ 2007-10-01 8:39 UTC (permalink / raw) To: Johannes Sixt; +Cc: Johannes Sixt, git Johannes Sixt <j.sixt@viscovery.net> writes: > Junio C Hamano schrieb: >> Johannes Sixt <johannes.sixt@telecom.at> writes: >> >>> This prepares the API of git_connect() and finish_connect() to operate on >>> a struct child_process. Currently, we just use that object as a placeholder >>> for the pid that we used to return. A follow-up patch will change the >>> implementation of git_connect() and finish_connect() to make full use >>> of the object. >> >> Good description, except removal of checks for negative return >> of the calling sites raised my eyebrow and had me spend a few >> more minutes to review than necessary (see below). > > I've thought about this issue a bit more. > > Letting git_connect() die on error unconditionally is poison for any > libification efforts. So here's a plan: > > 1. Let git_connect() return a struct child_process even for the > non-forking case. This way a return value of NULL can uniquely > identify a failure. > ... > Since my patch doesn't do (1), it can't do (2), i.e. keep the error > checks - > they must be removed because no unique failure value exists. So I > could complete (1) in a new version of this patch, in order to also do > (2). What is your preference? In any case, I'd rather first have one that hides fork/exec behind child_process first without changing the call to die() in git_connect() in this round. I am still in "post feature release clean-up" mood ;-) As to error indication, it somehow does not feel right to return something called "child _process_" structure when we want to tell the caller that there is no process to wait for in the no-error case, although the fact that we can use .in/.out fd in the structure when we _do_ have child process is attractive. As an alternative, we could keep the "NULL return means there was no need to fork" semantics of git_connect(), and instead add "int *status_ret" parameter for the caller to check. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t. 2007-10-01 8:39 ` Junio C Hamano @ 2007-10-01 9:08 ` Johannes Sixt 2007-10-02 17:54 ` Junio C Hamano 0 siblings, 1 reply; 30+ messages in thread From: Johannes Sixt @ 2007-10-01 9:08 UTC (permalink / raw) To: Junio C Hamano; +Cc: Johannes Sixt, git Junio C Hamano schrieb: > Johannes Sixt <j.sixt@viscovery.net> writes: >> Letting git_connect() die on error unconditionally is poison for any >> libification efforts. So here's a plan: >> >> 1. Let git_connect() return a struct child_process even for the >> non-forking case. This way a return value of NULL can uniquely >> identify a failure. >> ... >> Since my patch doesn't do (1), it can't do (2), i.e. keep the error >> checks - >> they must be removed because no unique failure value exists. So I >> could complete (1) in a new version of this patch, in order to also do >> (2). What is your preference? > > In any case, I'd rather first have one that hides fork/exec > behind child_process first without changing the call to die() in > git_connect() in this round. I am still in "post feature > release clean-up" mood ;-) Sure: The die()s are converted in a later step. My problem is that if I don't wrap the non-fork connections somehow in this first round, I *must* remove the error checks because there is no unique failure return value anymore. > As to error indication, it somehow does not feel right to return > something called "child _process_" structure when we want to > tell the caller that there is no process to wait for in the > no-error case, although the fact that we can use .in/.out fd in > the structure when we _do_ have child process is attractive. Did you mean: "even if we don't have a child process"? How about a typedef if you dislike the name? > As an alternative, we could keep the "NULL return means there > was no need to fork" semantics of git_connect(), and instead add > "int *status_ret" parameter for the caller to check. Seriously? Add an *out* parameter when we can get rid of one and have a return value, too? -- Hannes ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t. 2007-10-01 9:08 ` Johannes Sixt @ 2007-10-02 17:54 ` Junio C Hamano 0 siblings, 0 replies; 30+ messages in thread From: Junio C Hamano @ 2007-10-02 17:54 UTC (permalink / raw) To: Johannes Sixt; +Cc: Johannes Sixt, git Johannes Sixt <j.sixt@viscovery.net> writes: > Junio C Hamano schrieb: > ... >> As to error indication, it somehow does not feel right to return >> something called "child _process_" structure when we want to >> tell the caller that there is no process to wait for in the >> no-error case, although the fact that we can use .in/.out fd in >> the structure when we _do_ have child process is attractive. > > Did you mean: "even if we don't have a child process"? > > How about a typedef if you dislike the name? > >> As an alternative, we could keep the "NULL return means there >> was no need to fork" semantics of git_connect(), and instead add >> "int *status_ret" parameter for the caller to check. > > Seriously? Add an *out* parameter when we can get rid of one and have > a return value, too? Ah, I somehow got confused and thought that the caller decides not to do the waitpid business at the end of the connection, but as everybody calls finish_connect() with what it got from git_connect(), as long as the fake "child_process" structure records something to let finish_connect() know that it should not waitpid() on the process, all is well. It might make sense to teach finish_command() that a magic value of (cmd->pid == 0) means there is no process to wait for and this "child_process" structure is only about the in/out stream to the other side. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t. 2007-09-30 20:09 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt 2007-09-30 20:09 ` [PATCH 2/5] Use start_command() in git_connect() instead of explicit fork/exec Johannes Sixt 2007-09-30 20:43 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Junio C Hamano @ 2007-09-30 21:04 ` Johannes Schindelin 2 siblings, 0 replies; 30+ messages in thread From: Johannes Schindelin @ 2007-09-30 21:04 UTC (permalink / raw) To: Johannes Sixt; +Cc: gitster, git Hi, On Sun, 30 Sep 2007, Johannes Sixt wrote: > - pid_t pid; > + struct child_process *chld; Why not call it "child"? It's only one letter more, and much less confusing. > - pid = git_connect(fd, url, exec, 0); > - if (pid < 0) > - return pid; > + chld = git_connect(fd, url, exec, 0); chld never gets free()d. (I'm was about to suggest doing that in finish_command(), but I'm not quite sure what this would break.) > @@ -773,16 +773,14 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args, > st.st_mtime = 0; > } > > - pid = git_connect(fd, (char *)dest, uploadpack, > + chld = git_connect(fd, (char *)dest, uploadpack, > args.verbose ? CONNECT_VERBOSE : 0); > - if (pid < 0) > - return NULL; > if (heads && nr_heads) > nr_heads = remove_duplicates(nr_heads, heads); > ref = do_fetch_pack(fd, nr_heads, heads, pack_lockfile); In general, I would not lightly do away with the "return NULL" on error, since it is really hard to assess what do_fetch_pack() or packet_write() do (or don't) when git_connect() failed. > - while (waitpid(pid, NULL, 0) < 0) { > + while (waitpid(chld->pid, NULL, 0) < 0) { Shouldn't this be converted to finish_command() already? Ciao, Dscho ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 0/5] fork/exec removal series 2007-09-30 20:09 [PATCH 0/5] fork/exec removal series Johannes Sixt 2007-09-30 20:09 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt @ 2007-09-30 20:20 ` Junio C Hamano 2007-09-30 21:14 ` Johannes Schindelin 2 siblings, 0 replies; 30+ messages in thread From: Junio C Hamano @ 2007-09-30 20:20 UTC (permalink / raw) To: Johannes Sixt; +Cc: gitster, git Johannes Sixt <johannes.sixt@telecom.at> writes: > Here is a series of patches that removes a number fork/exec pairs. > They are replaced by delegating to start_command/finish_command/run_command. > You can regard this as the beginning of the MinGW port integration. Yay! > Patch 2 depends on Patch 1; otherwise, there are no dependencies. > The series goes on top of next (it touches str_buf stuff in connect.c). Thanks for an advance warning. I'll keep the series in my mailbox (promise) and queue it for 'pu' for now (but only if I have time), as I intend to merge the strbuf stuff to 'master' soon. ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 0/5] fork/exec removal series 2007-09-30 20:09 [PATCH 0/5] fork/exec removal series Johannes Sixt 2007-09-30 20:09 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt 2007-09-30 20:20 ` [PATCH 0/5] fork/exec removal series Junio C Hamano @ 2007-09-30 21:14 ` Johannes Schindelin 2007-09-30 21:34 ` Johannes Sixt 2 siblings, 1 reply; 30+ messages in thread From: Johannes Schindelin @ 2007-09-30 21:14 UTC (permalink / raw) To: Johannes Sixt; +Cc: gitster, git Hi, On Sun, 30 Sep 2007, Johannes Sixt wrote: > You can regard this as the beginning of the MinGW port integration. Thank you very much! This effort cannot be praised enough. > There still remain a few forks, which fall into these categories: > > - They are in tools or code that are not (yet) ported to MinGW.[*] The nice thing about the integration effort: It does not need to be done in one go. > - The fork()s are not followed by exec(). These need a different > implementation. I am thinking of a start_coroutine()/finish_coroutine() > API that is implemented with threads in MinGW. (Suggestions of a better > as well as implementations are welcome.) Is there more than the case I introduced with shallow clones? Thanks, Dscho ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 0/5] fork/exec removal series 2007-09-30 21:14 ` Johannes Schindelin @ 2007-09-30 21:34 ` Johannes Sixt 2007-09-30 21:43 ` Johannes Schindelin 0 siblings, 1 reply; 30+ messages in thread From: Johannes Sixt @ 2007-09-30 21:34 UTC (permalink / raw) To: git; +Cc: Johannes Schindelin, gitster On Sunday 30 September 2007 23:14, Johannes Schindelin wrote: > On Sun, 30 Sep 2007, Johannes Sixt wrote: > > - The fork()s are not followed by exec(). These need a different > > implementation. I am thinking of a start_coroutine()/finish_coroutine() > > API that is implemented with threads in MinGW. (Suggestions of a better > > as well as implementations are welcome.) > > Is there more than the case I introduced with shallow clones? I don't know which one you are refering to. These cases I hope to be able to treat as "coroutine": - sideband demultiplexer in builtin-fetch-pack.c - internal rev-list in upload-pack - the two-way pipe handling in convert.c and builtin-upload-archive.c There are probably more in daemon.c and imap-send.c. BTW, the convert.c case (apply_filter) is most interesting for me, since I have a real-world use-case for a clean-filter. -- Hannes ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 0/5] fork/exec removal series 2007-09-30 21:34 ` Johannes Sixt @ 2007-09-30 21:43 ` Johannes Schindelin 2007-10-01 7:07 ` Johannes Sixt 0 siblings, 1 reply; 30+ messages in thread From: Johannes Schindelin @ 2007-09-30 21:43 UTC (permalink / raw) To: Johannes Sixt; +Cc: git, gitster Hi, On Sun, 30 Sep 2007, Johannes Sixt wrote: > On Sunday 30 September 2007 23:14, Johannes Schindelin wrote: > > > Is there more than the case I introduced with shallow clones? > > I don't know which one you are refering to. The rev-list one in upload-pack. > These cases I hope to be able to treat as "coroutine": > > - sideband demultiplexer in builtin-fetch-pack.c > - internal rev-list in upload-pack > - the two-way pipe handling in convert.c and builtin-upload-archive.c > > There are probably more in daemon.c and imap-send.c. > > BTW, the convert.c case (apply_filter) is most interesting for me, since I > have a real-world use-case for a clean-filter. Calling it coroutine is interesting... But yes, I agree that these three cases cannot be handled otherwise. Ciao, Dscho ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 0/5] fork/exec removal series 2007-09-30 21:43 ` Johannes Schindelin @ 2007-10-01 7:07 ` Johannes Sixt 2007-10-01 9:49 ` David Kastrup 0 siblings, 1 reply; 30+ messages in thread From: Johannes Sixt @ 2007-10-01 7:07 UTC (permalink / raw) To: Johannes Schindelin; +Cc: Johannes Sixt, git, gitster Johannes Schindelin schrieb: > On Sun, 30 Sep 2007, Johannes Sixt wrote: >> These cases I hope to be able to treat as "coroutine": >> >> - sideband demultiplexer in builtin-fetch-pack.c >> - internal rev-list in upload-pack >> - the two-way pipe handling in convert.c and builtin-upload-archive.c >> >> There are probably more in daemon.c and imap-send.c. >> >> BTW, the convert.c case (apply_filter) is most interesting for me, since I >> have a real-world use-case for a clean-filter. > > Calling it coroutine is interesting... But yes, I agree that these three > cases cannot be handled otherwise. Suggestions for a better name are appreciated! -- Hannes ^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 0/5] fork/exec removal series 2007-10-01 7:07 ` Johannes Sixt @ 2007-10-01 9:49 ` David Kastrup 0 siblings, 0 replies; 30+ messages in thread From: David Kastrup @ 2007-10-01 9:49 UTC (permalink / raw) To: git Johannes Sixt <j.sixt@viscovery.net> writes: > Johannes Schindelin schrieb: >> On Sun, 30 Sep 2007, Johannes Sixt wrote: >>> These cases I hope to be able to treat as "coroutine": >>> >>> - sideband demultiplexer in builtin-fetch-pack.c >>> - internal rev-list in upload-pack >>> - the two-way pipe handling in convert.c and builtin-upload-archive.c >>> >>> There are probably more in daemon.c and imap-send.c. >>> >>> BTW, the convert.c case (apply_filter) is most interesting for me, >>> since I have a real-world use-case for a clean-filter. >> >> Calling it coroutine is interesting... But yes, I agree that these >> three cases cannot be handled otherwise. > > Suggestions for a better name are appreciated! I think coroutine is commonly used as the name for _synchronous_ context switches aka message passing. Basically the same as subroutine calls, except that the called subroutine has its own dynamic context (instruction pointer, call stack, control flow) that gets activated and suspended. If there is parallelism implied, "thread" is the more appropriate name. -- David Kastrup ^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2007-10-04 20:12 UTC | newest] Thread overview: 30+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-09-30 20:09 [PATCH 0/5] fork/exec removal series Johannes Sixt 2007-09-30 20:09 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt 2007-09-30 20:09 ` [PATCH 2/5] Use start_command() in git_connect() instead of explicit fork/exec Johannes Sixt 2007-09-30 20:09 ` [PATCH 3/5] Use start_command() to run the filter " Johannes Sixt 2007-09-30 20:10 ` [PATCH 4/5] Use run_command() to spawn external diff programs instead of fork/exec Johannes Sixt 2007-09-30 20:10 ` [PATCH 5/5] Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec Johannes Sixt 2007-09-30 21:10 ` [PATCH 4/5] Use run_command() to spawn external diff programs instead of fork/exec Johannes Schindelin 2007-09-30 21:07 ` [PATCH 3/5] Use start_command() to run the filter instead of explicit fork/exec Johannes Schindelin 2007-09-30 20:43 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Junio C Hamano 2007-09-30 21:40 ` Johannes Sixt 2007-10-03 20:09 ` [PATCH 0/5, resend] fork/exec removal series Johannes Sixt 2007-10-03 20:09 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt 2007-10-03 20:09 ` [PATCH 2/5] Use start_command() in git_connect() instead of explicit fork/exec Johannes Sixt 2007-10-03 20:09 ` [PATCH 3/5] Use start_command() to run the filter " Johannes Sixt 2007-10-03 20:09 ` [PATCH 4/5] Use run_command() to spawn external diff programs instead of fork/exec Johannes Sixt 2007-10-03 20:09 ` [PATCH 5/5] Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec Johannes Sixt 2007-10-04 8:55 ` Junio C Hamano 2007-10-04 9:22 ` Johannes Sixt 2007-10-04 20:11 ` Johannes Sixt 2007-10-01 7:23 ` [PATCH 1/5] Change git_connect() to return a struct child_process instead of a pid_t Johannes Sixt 2007-10-01 8:39 ` Junio C Hamano 2007-10-01 9:08 ` Johannes Sixt 2007-10-02 17:54 ` Junio C Hamano 2007-09-30 21:04 ` Johannes Schindelin 2007-09-30 20:20 ` [PATCH 0/5] fork/exec removal series Junio C Hamano 2007-09-30 21:14 ` Johannes Schindelin 2007-09-30 21:34 ` Johannes Sixt 2007-09-30 21:43 ` Johannes Schindelin 2007-10-01 7:07 ` Johannes Sixt 2007-10-01 9:49 ` David Kastrup
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).