@matheusbsbs / matheus-bagliano / commits / 30e1560230
Fork 0

daemon: use run-command api for async serving

fork() is only available on POSIX, so to support git-daemon on Windows we have to use something else. Instead we invent the flag --serve, which is a stripped down version of --inetd-mode. We use start_command() to call git-daemon with this flag appended to serve clients. Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Erik Faye-Lund committed Nov 4, 2010 at 02:35 UTC 30e1560230bc0154230b315a5f7c4f46870f9c81
1 file changed +47 -46
daemon.c
+47 -46
@@ -614,17 +614,17 @@ static unsigned int live_children;
614
615 static struct child {
616 struct child *next;
617 - pid_t pid;
617 + struct child_process cld;
618 struct sockaddr_storage address;
619 } *firstborn;
620
621 -static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)
621 +static void add_child(struct child_process *cld, struct sockaddr *addr, int addrlen)
622 {
623 struct child *newborn, **cradle;
624
625 newborn = xcalloc(1, sizeof(*newborn));
626 live_children++;
627 - newborn->pid = pid;
627 + memcpy(&newborn->cld, cld, sizeof(*cld));
628 memcpy(&newborn->address, addr, addrlen);
629 for (cradle = &firstborn; *cradle; cradle = &(*cradle)->next)
630 if (!addrcmp(&(*cradle)->address, &newborn->address))
@@ -633,19 +633,6 @@ static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)
633 *cradle = newborn;
634 }
635
636 -static void remove_child(pid_t pid)
637 -{
638 - struct child **cradle, *blanket;
639 -
640 - for (cradle = &firstborn; (blanket = *cradle); cradle = &blanket->next)
641 - if (blanket->pid == pid) {
642 - *cradle = blanket->next;
643 - live_children--;
644 - free(blanket);
645 - break;
646 - }
647 -}
648 -
636 /*
637 * This gets called if the number of connections grows
638 * past "max_connections".
@@ -661,7 +648,7 @@ static void kill_some_child(void)
648
649 for (; (next = blanket->next); blanket = next)
650 if (!addrcmp(&blanket->address, &next->address)) {
664 - kill(blanket->pid, SIGTERM);
651 + kill(blanket->cld.pid, SIGTERM);
652 break;
653 }
654 }
@@ -671,18 +658,26 @@ static void check_dead_children(void)
658 int status;
659 pid_t pid;
660
674 - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
675 - const char *dead = "";
676 - remove_child(pid);
677 - if (!WIFEXITED(status) || (WEXITSTATUS(status) > 0))
678 - dead = " (with error)";
679 - loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead);
680 - }
661 + struct child **cradle, *blanket;
662 + for (cradle = &firstborn; (blanket = *cradle);)
663 + if ((pid = waitpid(blanket->cld.pid, &status, WNOHANG)) > 1) {
664 + const char *dead = "";
665 + if (status)
666 + dead = " (with error)";
667 + loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead);
668 +
669 + /* remove the child */
670 + *cradle = blanket->next;
671 + live_children--;
672 + free(blanket);
673 + } else
674 + cradle = &blanket->next;
675 }
676
677 +static char **cld_argv;
678 static void handle(int incoming, struct sockaddr *addr, int addrlen)
679 {
685 - pid_t pid;
680 + struct child_process cld = { 0 };
681
682 if (max_connections && live_children >= max_connections) {
683 kill_some_child();
@@ -695,22 +690,15 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
690 }
691 }
692
698 - if ((pid = fork())) {
699 - close(incoming);
700 - if (pid < 0) {
701 - logerror("Couldn't fork %s", strerror(errno));
702 - return;
703 - }
704 -
705 - add_child(pid, addr, addrlen);
706 - return;
707 - }
693 + cld.argv = (const char **)cld_argv;
694 + cld.in = incoming;
695 + cld.out = dup(incoming);
696
709 - dup2(incoming, 0);
710 - dup2(incoming, 1);
697 + if (start_command(&cld))
698 + logerror("unable to fork");
699 + else
700 + add_child(&cld, addr, addrlen);
701 close(incoming);
712 -
713 - exit(execute(addr));
702 }
703
704 static void child_handler(int signo)
@@ -991,7 +979,7 @@ int main(int argc, char **argv)
979 {
980 int listen_port = 0;
981 struct string_list listen_addr = STRING_LIST_INIT_NODUP;
994 - int inetd_mode = 0;
982 + int serve_mode = 0, inetd_mode = 0;
983 const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
984 int detach = 0;
985 struct passwd *pass = NULL;
@@ -1017,6 +1005,10 @@ int main(int argc, char **argv)
1005 continue;
1006 }
1007 }
1008 + if (!strcmp(arg, "--serve")) {
1009 + serve_mode = 1;
1010 + continue;
1011 + }
1012 if (!strcmp(arg, "--inetd")) {
1013 inetd_mode = 1;
1014 log_syslog = 1;
@@ -1162,17 +1154,19 @@ int main(int argc, char **argv)
1154 base_path);
1155
1156 if (inetd_mode) {
1157 + if (!freopen("/dev/null", "w", stderr))
1158 + die_errno("failed to redirect stderr to /dev/null");
1159 + }
1160 +
1161 + if (inetd_mode || serve_mode) {
1162 struct sockaddr_storage ss;
1163 struct sockaddr *peer = (struct sockaddr *)&ss;
1164 socklen_t slen = sizeof(ss);
1165
1169 - if (!freopen("/dev/null", "w", stderr))
1170 - die_errno("failed to redirect stderr to /dev/null");
1171 -
1166 if (getpeername(0, peer, &slen))
1173 - peer = NULL;
1174 -
1175 - return execute(peer);
1167 + return execute(NULL);
1168 + else
1169 + return execute(peer);
1170 }
1171
1172 if (detach) {
@@ -1185,5 +1179,12 @@ int main(int argc, char **argv)
1179 if (pid_file)
1180 store_pid(pid_file);
1181
1182 + /* prepare argv for serving-processes */
1183 + cld_argv = xmalloc(sizeof (char *) * (argc + 2));
1184 + for (i = 0; i < argc; ++i)
1185 + cld_argv[i] = argv[i];
1186 + cld_argv[argc] = "--serve";
1187 + cld_argv[argc+1] = NULL;
1188 +
1189 return serve(&listen_addr, listen_port, pass, gid);
1190 }