зеркало из https://github.com/microsoft/git.git
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>
This commit is contained in:
Родитель
82fc07b7ba
Коммит
30e1560230
93
daemon.c
93
daemon.c
|
@ -614,17 +614,17 @@ static unsigned int live_children;
|
||||||
|
|
||||||
static struct child {
|
static struct child {
|
||||||
struct child *next;
|
struct child *next;
|
||||||
pid_t pid;
|
struct child_process cld;
|
||||||
struct sockaddr_storage address;
|
struct sockaddr_storage address;
|
||||||
} *firstborn;
|
} *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;
|
struct child *newborn, **cradle;
|
||||||
|
|
||||||
newborn = xcalloc(1, sizeof(*newborn));
|
newborn = xcalloc(1, sizeof(*newborn));
|
||||||
live_children++;
|
live_children++;
|
||||||
newborn->pid = pid;
|
memcpy(&newborn->cld, cld, sizeof(*cld));
|
||||||
memcpy(&newborn->address, addr, addrlen);
|
memcpy(&newborn->address, addr, addrlen);
|
||||||
for (cradle = &firstborn; *cradle; cradle = &(*cradle)->next)
|
for (cradle = &firstborn; *cradle; cradle = &(*cradle)->next)
|
||||||
if (!addrcmp(&(*cradle)->address, &newborn->address))
|
if (!addrcmp(&(*cradle)->address, &newborn->address))
|
||||||
|
@ -633,19 +633,6 @@ static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)
|
||||||
*cradle = newborn;
|
*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
|
* This gets called if the number of connections grows
|
||||||
* past "max_connections".
|
* past "max_connections".
|
||||||
|
@ -661,7 +648,7 @@ static void kill_some_child(void)
|
||||||
|
|
||||||
for (; (next = blanket->next); blanket = next)
|
for (; (next = blanket->next); blanket = next)
|
||||||
if (!addrcmp(&blanket->address, &next->address)) {
|
if (!addrcmp(&blanket->address, &next->address)) {
|
||||||
kill(blanket->pid, SIGTERM);
|
kill(blanket->cld.pid, SIGTERM);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -671,18 +658,26 @@ static void check_dead_children(void)
|
||||||
int status;
|
int status;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
|
struct child **cradle, *blanket;
|
||||||
const char *dead = "";
|
for (cradle = &firstborn; (blanket = *cradle);)
|
||||||
remove_child(pid);
|
if ((pid = waitpid(blanket->cld.pid, &status, WNOHANG)) > 1) {
|
||||||
if (!WIFEXITED(status) || (WEXITSTATUS(status) > 0))
|
const char *dead = "";
|
||||||
dead = " (with error)";
|
if (status)
|
||||||
loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char **cld_argv;
|
||||||
static void handle(int incoming, struct sockaddr *addr, int addrlen)
|
static void handle(int incoming, struct sockaddr *addr, int addrlen)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
struct child_process cld = { 0 };
|
||||||
|
|
||||||
if (max_connections && live_children >= max_connections) {
|
if (max_connections && live_children >= max_connections) {
|
||||||
kill_some_child();
|
kill_some_child();
|
||||||
|
@ -695,22 +690,15 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pid = fork())) {
|
cld.argv = (const char **)cld_argv;
|
||||||
close(incoming);
|
cld.in = incoming;
|
||||||
if (pid < 0) {
|
cld.out = dup(incoming);
|
||||||
logerror("Couldn't fork %s", strerror(errno));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
add_child(pid, addr, addrlen);
|
if (start_command(&cld))
|
||||||
return;
|
logerror("unable to fork");
|
||||||
}
|
else
|
||||||
|
add_child(&cld, addr, addrlen);
|
||||||
dup2(incoming, 0);
|
|
||||||
dup2(incoming, 1);
|
|
||||||
close(incoming);
|
close(incoming);
|
||||||
|
|
||||||
exit(execute(addr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void child_handler(int signo)
|
static void child_handler(int signo)
|
||||||
|
@ -991,7 +979,7 @@ int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int listen_port = 0;
|
int listen_port = 0;
|
||||||
struct string_list listen_addr = STRING_LIST_INIT_NODUP;
|
struct string_list listen_addr = STRING_LIST_INIT_NODUP;
|
||||||
int inetd_mode = 0;
|
int serve_mode = 0, inetd_mode = 0;
|
||||||
const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
|
const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
|
||||||
int detach = 0;
|
int detach = 0;
|
||||||
struct passwd *pass = NULL;
|
struct passwd *pass = NULL;
|
||||||
|
@ -1017,6 +1005,10 @@ int main(int argc, char **argv)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!strcmp(arg, "--serve")) {
|
||||||
|
serve_mode = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!strcmp(arg, "--inetd")) {
|
if (!strcmp(arg, "--inetd")) {
|
||||||
inetd_mode = 1;
|
inetd_mode = 1;
|
||||||
log_syslog = 1;
|
log_syslog = 1;
|
||||||
|
@ -1162,17 +1154,19 @@ int main(int argc, char **argv)
|
||||||
base_path);
|
base_path);
|
||||||
|
|
||||||
if (inetd_mode) {
|
if (inetd_mode) {
|
||||||
|
if (!freopen("/dev/null", "w", stderr))
|
||||||
|
die_errno("failed to redirect stderr to /dev/null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inetd_mode || serve_mode) {
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
struct sockaddr *peer = (struct sockaddr *)&ss;
|
struct sockaddr *peer = (struct sockaddr *)&ss;
|
||||||
socklen_t slen = sizeof(ss);
|
socklen_t slen = sizeof(ss);
|
||||||
|
|
||||||
if (!freopen("/dev/null", "w", stderr))
|
|
||||||
die_errno("failed to redirect stderr to /dev/null");
|
|
||||||
|
|
||||||
if (getpeername(0, peer, &slen))
|
if (getpeername(0, peer, &slen))
|
||||||
peer = NULL;
|
return execute(NULL);
|
||||||
|
else
|
||||||
return execute(peer);
|
return execute(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (detach) {
|
if (detach) {
|
||||||
|
@ -1185,5 +1179,12 @@ int main(int argc, char **argv)
|
||||||
if (pid_file)
|
if (pid_file)
|
||||||
store_pid(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);
|
return serve(&listen_addr, listen_port, pass, gid);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче