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
}