daemon: enable SO_KEEPALIVE for all sockets
authorEric Wong <e@80x24.org>
Wed, 25 May 2016 03:15:05 +0000 (03:15 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 25 May 2016 16:42:53 +0000 (09:42 -0700)
While --init-timeout and --timeout options exist and I've never
run git-daemon without them, some users may forget to set them
and encounter hung daemon processes when connections fail.
Enable socket-level timeouts so the kernel can send keepalive
probes as necessary to detect failed connections.

Signed-off-by: Eric Wong <e@80x24.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
daemon.c
index 8d45c336f5f816768962c39e8af6b10e0bb0e21e..46dddaca5a05a4d50da21c828085168e3ebe8b86 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -669,6 +669,15 @@ static void hostinfo_clear(struct hostinfo *hi)
        strbuf_release(&hi->tcp_port);
 }
 
+static void set_keep_alive(int sockfd)
+{
+       int ka = 1;
+
+       if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &ka, sizeof(ka)) < 0)
+               logerror("unable to set SO_KEEPALIVE on socket: %s",
+                       strerror(errno));
+}
+
 static int execute(void)
 {
        char *line = packet_buffer;
@@ -681,6 +690,7 @@ static int execute(void)
        if (addr)
                loginfo("Connection from %s:%s", addr, port);
 
+       set_keep_alive(0);
        alarm(init_timeout ? init_timeout : timeout);
        pktlen = packet_read(0, NULL, NULL, packet_buffer, sizeof(packet_buffer), 0);
        alarm(0);
@@ -951,6 +961,8 @@ static int setup_named_sock(char *listen_addr, int listen_port, struct socketlis
                        continue;
                }
 
+               set_keep_alive(sockfd);
+
                if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
                        logerror("Could not bind to %s: %s",
                                 ip2str(ai->ai_family, ai->ai_addr, ai->ai_addrlen),
@@ -1010,6 +1022,8 @@ static int setup_named_sock(char *listen_addr, int listen_port, struct socketlis
                return 0;
        }
 
+       set_keep_alive(sockfd);
+
        if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
                logerror("Could not bind to %s: %s",
                         ip2str(AF_INET, (struct sockaddr *)&sin, sizeof(sin)),