found 627268 git/1:1.7.9.5-1 tags 627268 + patch quit Jonathan Nieder wrote:
> 3. git-daemon gets EADDRINUSE when it tries to use that address, since > the SO_REUSEADDR flag is not set. If all (usually meaning "both") > addresses to be bound to are "in use", the daemon dies with > > fatal: unable to allocate any listen sockets on port 9418 > > and gets launched again by runit when an address is free. > > If only _some_ of the addresses to be bound to are "in use" in this > way, the daemon does not get launched again, and it is bound only > to the remaining ones. Here's a patch that makes it possible to use --listen=0.0.0.0 --listen=::0 --listen-strict in the "git daemon" arguments in /etc/sv/git-daemon/run to avoid that problem. -- >8 -- Subject: daemon: optionally treat failure to listen as a fatal error Asking the git daemon to listen over multiple protocols is currently somewhat error prone. For example, suppose I perform the following steps: 1. Launch the git daemon: git daemon --verbose --listen=0.0.0.0 --listen=::0 \ --base-path=/srv/git /srv/git 2. Start a connection: git clone git://127.0.0.1/git.git 3. While it is transferring objects, interrupt the daemon and launch it again: killall -9 git-daemon git daemon --verbose --listen=0.0.0.0 --listen=::0 ... 4. Start another connection: git clone git://127.0.0.1/git.git Then although the second launch of the "git daemon" server (step 3) succeeds, the second client (step 4) fails with "Connection refused". The cause is that because we did not pass --reuseaddr to the daemon, it receives EADDRINUSE when it tries to bind to the ipv4 wildcard address which is in use. (--reuseaddr should probably be enabled by default, but that's not what this patch is about.) This is a common cause of bind(2) failure in daemons and it is not entirely unexpected that listening to INADDR_ANY fails. What is surprising is that "git daemon" only logs the event and does not exit to signal the error. The logic is that as long as the daemon binds to _some_ address (in this example the ipv6 one) it has in some sense succeeded. It would be better to error out when the daemon is not able to fulfill the administrator's request by listening to all of the addresses requested on the command line. Do so when requested by passing --listen-strict on the command line. Making the improvement opt-in means configurations that relied on the existing, more permissive behavior will not be broken by this change. Signed-off-by: Jonathan Nieder <jrnie...@gmail.com> --- Documentation/git-daemon.txt | 7 ++++++- daemon.c | 20 +++++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt index 31b28fc2..bd061b7f 100644 --- a/Documentation/git-daemon.txt +++ b/Documentation/git-daemon.txt @@ -16,7 +16,8 @@ SYNOPSIS [--reuseaddr] [--detach] [--pid-file=<file>] [--enable=<service>] [--disable=<service>] [--allow-override=<service>] [--forbid-override=<service>] - [--inetd | [--listen=<host_or_ipaddr>] [--port=<n>] [--user=<user> [--group=<group>]] + [--inetd | [--listen=<host_or_ipaddr>] [--port=<n>] + [--listen-strict] [--user=<user> [--group=<group>]]] [<directory>...] DESCRIPTION @@ -92,6 +93,10 @@ OPTIONS --port=<n>:: Listen on an alternative port. Incompatible with '--inetd' option. +--listen-strict:: + Exit if listening to one of the addresses specified using the + '--listen' option fails. + --init-timeout=<n>:: Timeout (in seconds) between the moment the connection is established and the client request is received (typically a rather low value, since diff --git a/daemon.c b/daemon.c index ab21e66b..7e1a18ed 100644 --- a/daemon.c +++ b/daemon.c @@ -20,6 +20,7 @@ static int log_syslog; static int verbose; static int reuseaddr; +static int listen_failure_is_fatal; static int informative_errors; static const char daemon_usage[] = @@ -913,12 +914,17 @@ static void socksetup(struct string_list *listen_addr, int listen_port, struct s else { int i, socknum; for (i = 0; i < listen_addr->nr; i++) { - socknum = setup_named_sock(listen_addr->items[i].string, - listen_port, socklist); + char *addr = listen_addr->items[i].string; - if (socknum == 0) - logerror("unable to allocate any listen sockets for host %s on port %u", - listen_addr->items[i].string, listen_port); + socknum = setup_named_sock(addr, listen_port, socklist); + if (socknum) + continue; + + logerror("unable to allocate any listen sockets for host %s on port %u", + addr, listen_port); + if (listen_failure_is_fatal) + die("unable to allocate any listen sockets for host %s on port %u", + addr, listen_port); } } } @@ -1121,6 +1127,10 @@ int main(int argc, char **argv) continue; } } + if (!strcmp(arg, "--listen-strict")) { + listen_failure_is_fatal = 1; + continue; + } if (!strcmp(arg, "--serve")) { serve_mode = 1; continue; -- 1.7.10.rc3 -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org