fork() is only available on POSIX, so to support git-daemon on Windows we have to use something else. Conveniently enough, we have an API for async operation already. Signed-off-by: Erik Faye-Lund <kusmabite@xxxxxxxxx> --- daemon.c | 87 +++++++++++++++++++++++++++++++------------------------------ 1 files changed, 44 insertions(+), 43 deletions(-) diff --git a/daemon.c b/daemon.c index b42792f..2d63cbc 100644 --- a/daemon.c +++ b/daemon.c @@ -583,17 +583,17 @@ static unsigned int live_children; static struct child { struct child *next; - pid_t pid; + struct child_process cld; struct sockaddr_storage address; } *firstborn; -static void add_child(pid_t pid, struct sockaddr *addr, int addrlen) +static void add_child(struct child_process *cld, struct sockaddr *addr, int addrlen) { struct child *newborn, **cradle; newborn = xcalloc(1, sizeof(*newborn)); live_children++; - newborn->pid = pid; + memcpy(&newborn->cld, cld, sizeof(*cld)); memcpy(&newborn->address, addr, addrlen); for (cradle = &firstborn; *cradle; cradle = &(*cradle)->next) if (!addrcmp(&(*cradle)->address, &newborn->address)) @@ -602,19 +602,6 @@ static void add_child(pid_t pid, struct sockaddr *addr, int addrlen) *cradle = newborn; } -static void remove_child(pid_t pid) -{ - struct child **cradle, *blanket; - - for (cradle = &firstborn; (blanket = *cradle); cradle = &blanket->next) - if (blanket->pid == pid) { - *cradle = blanket->next; - live_children--; - free(blanket); - break; - } -} - /* * This gets called if the number of connections grows * past "max_connections". @@ -623,14 +610,14 @@ static void remove_child(pid_t pid) */ static void kill_some_child(void) { - const struct child *blanket, *next; + struct child *blanket, *next; if (!(blanket = firstborn)) return; for (; (next = blanket->next); blanket = next) if (!addrcmp(&blanket->address, &next->address)) { - kill(blanket->pid, SIGTERM); + kill(blanket->cld.pid, SIGTERM); break; } } @@ -640,19 +627,26 @@ static void check_dead_children(void) int status; pid_t pid; - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { - const char *dead = ""; - remove_child(pid); - if (!WIFEXITED(status) || (WEXITSTATUS(status) > 0)) - dead = " (with error)"; - loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead); - } + struct child **cradle, *blanket; + for (cradle = &firstborn; (blanket = *cradle);) + if ((pid = waitpid(blanket->cld.pid, &status, WNOHANG)) > 1) { + const char *dead = ""; + if (status) + dead = " (with error)"; + loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead); + + /* remove the child */ + *cradle = blanket->next; + live_children--; + free(blanket); + } else + cradle = &blanket->next; } +char **cld_argv; static void handle(int incoming, struct sockaddr *addr, int addrlen) { - int fd[2]; - pid_t pid; + struct child_process cld = { 0 }; if (max_connections && live_children >= max_connections) { kill_some_child(); @@ -665,20 +659,15 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen) } } - if ((pid = fork())) { - close(incoming); - if (pid < 0) { - logerror("Couldn't fork %s", strerror(errno)); - return; - } - - add_child(pid, addr, addrlen); - return; - } + cld.argv = (const char **)cld_argv; + cld.in = incoming; + cld.out = dup(incoming); - fd[0] = incoming; - fd[1] = dup(incoming); - exit(execute(fd, addr)); + if (start_command(&cld)) + logerror("unable to fork"); + else + add_child(&cld, addr, addrlen); + close(incoming); } static void child_handler(int signo) @@ -934,7 +923,7 @@ int main(int argc, char **argv) { int listen_port = 0; char *listen_addr = NULL; - int inetd_mode = 0; + int serve_mode = 0, inetd_mode = 0; const char *pid_file = NULL, *user_name = NULL, *group_name = NULL; int detach = 0; struct passwd *pass = NULL; @@ -960,7 +949,12 @@ int main(int argc, char **argv) continue; } } + if (!strcmp(arg, "--serve")) { + serve_mode = 1; + continue; + } if (!strcmp(arg, "--inetd")) { + serve_mode = 1; inetd_mode = 1; log_syslog = 1; continue; @@ -1104,13 +1098,13 @@ int main(int argc, char **argv) die("base-path '%s' does not exist or is not a directory", base_path); - if (inetd_mode) { + if (serve_mode) { int fd[2] = { 0, 1 }; struct sockaddr_storage ss; struct sockaddr *peer = (struct sockaddr *)&ss; socklen_t slen = sizeof(ss); - if (!freopen("/dev/null", "w", stderr)) + if (inetd_mode && !freopen("/dev/null", "w", stderr)) die_errno("failed to redirect stderr to /dev/null"); if (getpeername(0, peer, &slen)) @@ -1129,5 +1123,12 @@ int main(int argc, char **argv) if (pid_file) store_pid(pid_file); + /* prepare argv for serving-processes */ + cld_argv = xmalloc(sizeof (char *) * (argc + 2)); + for (i = 0; i < argc; ++i) + cld_argv[i] = argv[i]; + cld_argv[argc] = "--serve"; + cld_argv[argc+1] = NULL; + return serve(listen_addr, listen_port, pass, gid); } -- 1.6.6.211.g26720 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html