{"thread":{"id":"15009","subject":"[PATCH 2/4] git-daemon: use LOG_PID, simplify logging code","startedAt":"2008-08-14T18:02:20Z","lastAt":"2008-08-14T18:02:20Z","messageCount":4,"participants":["Stephen R. van den Berg"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"87213","messageId":"20080814180220.15729.85509.stgit@aristoteles.cuci.nl","threadId":"15009","inReplyTo":"20080814180220.15729.34048.stgit@aristoteles.cuci.nl","subject":"[PATCH 2/4] git-daemon: use LOG_PID, simplify logging code","fromName":"Stephen R. van den Berg","fromEmail":"srb@cuci.nl","sentAt":"2008-08-14T18:02:20Z","receivedAt":"2008-08-14T18:02:20Z","isPatch":true,"sender":{"key":"srb@cuci.nl","avatar":"https://gravatar.com/avatar/f75389059e827634d38e9df2a9b6ecbd50028b5a454442efa1c7205b7ff29c6a?d=mp&s=160"},"body":"Make git-daemon use LOG_PID like most daemons.\nCleanup buffering code for logging.\nUse linebuffering for stderr when logging to files.\nLog message at startup.\n\nSigned-off-by: Stephen R. van den Berg <srb@cuci.nl>\n---\n\n daemon.c |   47 ++++++++++++++++-------------------------------\n 1 files changed, 16 insertions(+), 31 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex 93e1106..2f86671 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -78,38 +78,19 @@ static struct interp interp_table[] = {\n \n static void logreport(int priority, const char *err, va_list params)\n {\n-\t/* We should do a single write so that it is atomic and output\n-\t * of several processes do not get intermingled. */\n-\tchar buf[1024];\n-\tint buflen;\n-\tint maxlen, msglen;\n-\n-\t/* sizeof(buf) should be big enough for \"[pid] \\n\" */\n-\tbuflen = snprintf(buf, sizeof(buf), \"[%ld] \", (long) getpid());\n-\n-\tmaxlen = sizeof(buf) - buflen - 1; /* -1 for our own LF */\n-\tmsglen = vsnprintf(buf + buflen, maxlen, err, params);\n-\n \tif (log_syslog) {\n+\t\tchar buf[1024];\n+\t\tvsnprintf(buf, sizeof(buf), err, params);\n \t\tsyslog(priority, \"%s\", buf);\n-\t\treturn;\n \t}\n-\n-\t/* maxlen counted our own LF but also counts space given to\n-\t * vsnprintf for the terminating NUL.  We want to make sure that\n-\t * we have space for our own LF and NUL after the \"meat\" of the\n-\t * message, so truncate it at maxlen - 1.\n-\t */\n-\tif (msglen > maxlen - 1)\n-\t\tmsglen = maxlen - 1;\n-\telse if (msglen < 0)\n-\t\tmsglen = 0; /* Protect against weird return values. */\n-\tbuflen += msglen;\n-\n-\tbuf[buflen++] = '\\n';\n-\tbuf[buflen] = '\\0';\n-\n-\twrite_in_full(2, buf, buflen);\n+\telse {\n+\t\t/* Since stderr is set to linebuffered mode, the\n+\t\t * logging of different processes will not overlap\n+\t\t */\n+\t\tfprintf(stderr, \"[%d] \", (int)getpid());\n+\t\tvfprintf(stderr, err, params);\n+\t\tfputc('\\n', stderr);\n+\t}\n }\n \n static void logerror(const char *err, ...)\n@@ -1178,9 +1159,11 @@ int main(int argc, char **argv)\n \t}\n \n \tif (log_syslog) {\n-\t\topenlog(\"git-daemon\", 0, LOG_DAEMON);\n+\t\topenlog(\"git-daemon\", LOG_PID, LOG_DAEMON);\n \t\tset_die_routine(daemon_die);\n \t}\n+\telse\t\t\t    /* so that logging into a file is atomic */\n+\t\tsetlinebuf(stderr);\n \n \tif (inetd_mode && (group_name || user_name))\n \t\tdie(\"--user and --group are incompatible with --inetd\");\n@@ -1233,8 +1216,10 @@ int main(int argc, char **argv)\n \t\treturn execute(peer);\n \t}\n \n-\tif (detach)\n+\tif (detach) {\n \t\tdaemonize();\n+\t\tloginfo(\"Ready to rumble\");\n+\t}\n \telse\n \t\tsanitize_stdfds();\n \n"},{"id":"87214","messageId":"20080814180220.15729.5512.stgit@aristoteles.cuci.nl","threadId":"15009","inReplyTo":"20080814180220.15729.34048.stgit@aristoteles.cuci.nl","subject":"[PATCH 3/4] git-daemon: move almost all code out of the child_handler()","fromName":"Stephen R. van den Berg","fromEmail":"srb@cuci.nl","sentAt":"2008-08-14T18:02:20Z","receivedAt":"2008-08-14T18:02:20Z","isPatch":true,"sender":{"key":"srb@cuci.nl","avatar":"https://gravatar.com/avatar/f75389059e827634d38e9df2a9b6ecbd50028b5a454442efa1c7205b7ff29c6a?d=mp&s=160"},"body":"into check_dead_children().\nThe fact that systemcalls get interrupted by signals allows us to\nmake the SIGCHLD signal handler almost a no-op by simply running\ncheck_dead_children() right before waiting on poll().\n\nFor those concerned with portability to \"awkward\" systems:\nIn case some systems do not interrupt systemcalls upon signal receipt,\nall zombies will eventually be collected before the next poll() cycle.\n\nSigned-off-by: Stephen R. van den Berg <srb@cuci.nl>\n---\n\n daemon.c |   55 +++++++++++++++++++++++--------------------------------\n 1 files changed, 23 insertions(+), 32 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex 2f86671..77bd8e1 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -16,7 +16,6 @@\n static int log_syslog;\n static int verbose;\n static int reuseaddr;\n-static int child_handler_pipe[2];\n \n static const char daemon_usage[] =\n \"git daemon [--verbose] [--syslog] [--export-all]\\n\"\n@@ -680,6 +679,21 @@ static void check_dead_children(void)\n {\n \tunsigned spawned, reaped, deleted;\n \n+\tfor (;;) {\n+\t    int status;\n+\t    pid_t pid = waitpid(-1, &status, WNOHANG);\n+\t\n+\t    if (pid > 0) {\n+\t        unsigned reaped = children_reaped;\n+\t        if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)\n+\t            pid = -pid;\n+\t        dead_child[reaped % MAX_CHILDREN] = pid;\n+\t        children_reaped = reaped + 1;\n+\t        continue;\n+\t    }\n+\t    break;\n+\t}\n+\n \tspawned = children_spawned;\n \treaped = children_reaped;\n \tdeleted = children_deleted;\n@@ -760,21 +774,10 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)\n \n static void child_handler(int signo)\n {\n-\tfor (;;) {\n-\t\tint status;\n-\t\tpid_t pid = waitpid(-1, &status, WNOHANG);\n-\n-\t\tif (pid > 0) {\n-\t\t\tunsigned reaped = children_reaped;\n-\t\t\tif (!WIFEXITED(status) || WEXITSTATUS(status) > 0)\n-\t\t\t\tpid = -pid;\n-\t\t\tdead_child[reaped % MAX_CHILDREN] = pid;\n-\t\t\tchildren_reaped = reaped + 1;\n-\t\t\twrite(child_handler_pipe[1], &status, 1);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tbreak;\n-\t}\n+\t/* Otherwise empty handler because systemcalls will get interrupted\n+\t * upon signal receipt\n+\t * SysV needs the handler to be rearmed\n+\t */\n \tsignal(SIGCHLD, child_handler);\n }\n \n@@ -917,24 +920,21 @@ static int service_loop(int socknum, int *socklist)\n \tstruct pollfd *pfd;\n \tint i;\n \n-\tif (pipe(child_handler_pipe) < 0)\n-\t\tdie (\"Could not set up pipe for child handler\");\n-\n-\tpfd = xcalloc(socknum + 1, sizeof(struct pollfd));\n+\tpfd = xcalloc(socknum, sizeof(struct pollfd));\n \n \tfor (i = 0; i < socknum; i++) {\n \t\tpfd[i].fd = socklist[i];\n \t\tpfd[i].events = POLLIN;\n \t}\n-\tpfd[socknum].fd = child_handler_pipe[0];\n-\tpfd[socknum].events = POLLIN;\n \n \tsignal(SIGCHLD, child_handler);\n \n \tfor (;;) {\n \t\tint i;\n \n-\t\tif (poll(pfd, socknum + 1, -1) < 0) {\n+\t\tcheck_dead_children();\n+\n+\t\tif (poll(pfd, socknum, -1) < 0) {\n \t\t\tif (errno != EINTR) {\n \t\t\t\tlogerror(\"Poll failed, resuming: %s\",\n \t\t\t\t      strerror(errno));\n@@ -942,10 +942,6 @@ static int service_loop(int socknum, int *socklist)\n \t\t\t}\n \t\t\tcontinue;\n \t\t}\n-\t\tif (pfd[socknum].revents & POLLIN) {\n-\t\t\tread(child_handler_pipe[0], &i, 1);\n-\t\t\tcheck_dead_children();\n-\t\t}\n \n \t\tfor (i = 0; i < socknum; i++) {\n \t\t\tif (pfd[i].revents & POLLIN) {\n@@ -1036,11 +1032,6 @@ int main(int argc, char **argv)\n \tgid_t gid = 0;\n \tint i;\n \n-\t/* Without this we cannot rely on waitpid() to tell\n-\t * what happened to our children.\n-\t */\n-\tsignal(SIGCHLD, SIG_DFL);\n-\n \tfor (i = 1; i < argc; i++) {\n \t\tchar *arg = argv[i];\n \n"},{"id":"87215","messageId":"20080814180220.15729.51838.stgit@aristoteles.cuci.nl","threadId":"15009","inReplyTo":"20080814180220.15729.34048.stgit@aristoteles.cuci.nl","subject":"[PATCH 4/4] git-daemon: rewrite kindergarden, new option --max-connections","fromName":"Stephen R. van den Berg","fromEmail":"srb@cuci.nl","sentAt":"2008-08-14T18:02:20Z","receivedAt":"2008-08-14T18:02:20Z","isPatch":true,"sender":{"key":"srb@cuci.nl","avatar":"https://gravatar.com/avatar/f75389059e827634d38e9df2a9b6ecbd50028b5a454442efa1c7205b7ff29c6a?d=mp&s=160"},"body":"Get rid of the fixed array of children and make max-connections\ndynamic and configurable.\nFix the killing code to actually kill the newest connections from\nduplicate IP-addresses.\nAvoid forking if too busy already.\n\nSigned-off-by: Stephen R. van den Berg <srb@cuci.nl>\n---\n\n Documentation/git-daemon.txt |    9 +-\n daemon.c                     |  213 +++++++++++++++---------------------------\n 2 files changed, 82 insertions(+), 140 deletions(-)\n\ndiff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt\nindex 4ba4b75..b08a08c 100644\n--- a/Documentation/git-daemon.txt\n+++ b/Documentation/git-daemon.txt\n@@ -9,8 +9,9 @@ SYNOPSIS\n --------\n [verse]\n 'git daemon' [--verbose] [--syslog] [--export-all]\n-\t     [--timeout=n] [--init-timeout=n] [--strict-paths]\n-\t     [--base-path=path] [--user-path | --user-path=path]\n+\t     [--timeout=n] [--init-timeout=n] [--max-connections=n]\n+\t     [--strict-paths] [--base-path=path] [--base-path-relaxed]\n+\t     [--user-path | --user-path=path]\n \t     [--interpolated-path=pathtemplate]\n \t     [--reuseaddr] [--detach] [--pid-file=file]\n \t     [--enable=service] [--disable=service]\n@@ -99,6 +100,10 @@ OPTIONS\n \tit takes for the server to process the sub-request and time spent\n \twaiting for next client's request.\n \n+--max-connections::\n+\tMaximum number of concurrent clients, defaults to 32.  Set it to\n+\tzero for no limit.\n+\n --syslog::\n \tLog to syslog instead of stderr. Note that this option does not imply\n \t--verbose, thus by default only error conditions will be logged.\ndiff --git a/daemon.c b/daemon.c\nindex 77bd8e1..61a3920 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -19,8 +19,8 @@ static int reuseaddr;\n \n static const char daemon_usage[] =\n \"git daemon [--verbose] [--syslog] [--export-all]\\n\"\n-\"           [--timeout=n] [--init-timeout=n] [--strict-paths]\\n\"\n-\"           [--base-path=path] [--base-path-relaxed]\\n\"\n+\"           [--timeout=n] [--init-timeout=n] [--max-connections=n]\\n\"\n+\"           [--strict-paths] [--base-path=path] [--base-path-relaxed]\\n\"\n \"           [--user-path | --user-path=path]\\n\"\n \"           [--interpolated-path=path]\\n\"\n \"           [--reuseaddr] [--detach] [--pid-file=file]\\n\"\n@@ -584,40 +584,35 @@ static int execute(struct sockaddr *addr)\n \treturn -1;\n }\n \n+static int max_connections = 32;\n \n-/*\n- * We count spawned/reaped separately, just to avoid any\n- * races when updating them from signals. The SIGCHLD handler\n- * will only update children_reaped, and the fork logic will\n- * only update children_spawned.\n- *\n- * MAX_CHILDREN should be a power-of-two to make the modulus\n- * operation cheap. It should also be at least twice\n- * the maximum number of connections we will ever allow.\n- */\n-#define MAX_CHILDREN 128\n-\n-static int max_connections = 25;\n-\n-/* These are updated by the signal handler */\n-static volatile unsigned int children_reaped;\n-static pid_t dead_child[MAX_CHILDREN];\n-\n-/* These are updated by the main loop */\n-static unsigned int children_spawned;\n-static unsigned int children_deleted;\n+static unsigned int live_children;\n \n static struct child {\n+\tstruct child *next;\n \tpid_t pid;\n-\tint addrlen;\n \tstruct sockaddr_storage address;\n-} live_child[MAX_CHILDREN];\n+} *firstborn;\n \n-static void add_child(int idx, pid_t pid, struct sockaddr *addr, int addrlen)\n+static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)\n {\n-\tlive_child[idx].pid = pid;\n-\tlive_child[idx].addrlen = addrlen;\n-\tmemcpy(&live_child[idx].address, addr, addrlen);\n+\tstruct child *newborn;\n+\tnewborn = xcalloc(1, sizeof *newborn);\n+\tif (newborn) {\n+\t\tstruct child **cradle;\n+\n+\t\tlive_children++;\n+\t\tnewborn->pid = pid;\n+\t\tmemcpy(&newborn->address, addr, addrlen);\n+\t\tfor (cradle = &firstborn; *cradle; cradle = &(*cradle)->next)\n+\t\t\tif (!memcmp(&(*cradle)->address, &newborn->address,\n+\t\t\t\t   sizeof newborn->address))\n+\t\t\t\tbreak;\n+\t\tnewborn->next = *cradle;\n+\t\t*cradle = newborn;\n+\t}\n+\telse\n+\t\tlogerror(\"Out of memory spawning new child\");\n }\n \n /*\n@@ -626,142 +621,78 @@ static void add_child(int idx, pid_t pid, struct sockaddr *addr, int addrlen)\n  * We move everything up by one, since the new \"deleted\" will\n  * be one higher.\n  */\n-static void remove_child(pid_t pid, unsigned deleted, unsigned spawned)\n+static void remove_child(pid_t pid)\n {\n-\tstruct child n;\n+\tstruct child **cradle, *blanket;\n \n-\tdeleted %= MAX_CHILDREN;\n-\tspawned %= MAX_CHILDREN;\n-\tif (live_child[deleted].pid == pid) {\n-\t\tlive_child[deleted].pid = -1;\n-\t\treturn;\n-\t}\n-\tn = live_child[deleted];\n-\tfor (;;) {\n-\t\tstruct child m;\n-\t\tdeleted = (deleted + 1) % MAX_CHILDREN;\n-\t\tif (deleted == spawned)\n-\t\t\tdie(\"could not find dead child %d\\n\", pid);\n-\t\tm = live_child[deleted];\n-\t\tlive_child[deleted] = n;\n-\t\tif (m.pid == pid)\n-\t\t\treturn;\n-\t\tn = m;\n-\t}\n+\tfor (cradle = &firstborn; (blanket = *cradle); cradle = &blanket->next)\n+\t\tif (blanket->pid == pid) {\n+\t\t\t*cradle = blanket->next;\n+\t\t\tlive_children--;\n+\t\t\tfree(blanket);\n+\t\t\tbreak;\n+\t\t}\n }\n \n /*\n  * This gets called if the number of connections grows\n  * past \"max_connections\".\n  *\n- * We _should_ start off by searching for connections\n- * from the same IP, and if there is some address wth\n- * multiple connections, we should kill that first.\n- *\n- * As it is, we just \"randomly\" kill 25% of the connections,\n- * and our pseudo-random generator sucks too. I have no\n- * shame.\n- *\n- * Really, this is just a place-holder for a _real_ algorithm.\n+ * We kill the newest connection from a duplicate IP.\n  */\n-static void kill_some_children(int signo, unsigned start, unsigned stop)\n+static void kill_some_child()\n {\n-\tstart %= MAX_CHILDREN;\n-\tstop %= MAX_CHILDREN;\n-\twhile (start != stop) {\n-\t\tif (!(start & 3))\n-\t\t\tkill(live_child[start].pid, signo);\n-\t\tstart = (start + 1) % MAX_CHILDREN;\n-\t}\n-}\n-\n-static void check_dead_children(void)\n-{\n-\tunsigned spawned, reaped, deleted;\n-\n-\tfor (;;) {\n-\t    int status;\n-\t    pid_t pid = waitpid(-1, &status, WNOHANG);\n-\t\n-\t    if (pid > 0) {\n-\t        unsigned reaped = children_reaped;\n-\t        if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)\n-\t            pid = -pid;\n-\t        dead_child[reaped % MAX_CHILDREN] = pid;\n-\t        children_reaped = reaped + 1;\n-\t        continue;\n-\t    }\n-\t    break;\n-\t}\n+\tconst struct child *blanket;\n \n-\tspawned = children_spawned;\n-\treaped = children_reaped;\n-\tdeleted = children_deleted;\n+\tif ((blanket = firstborn)) {\n+\t\tconst struct child *next;\n \n-\twhile (deleted < reaped) {\n-\t\tpid_t pid = dead_child[deleted % MAX_CHILDREN];\n-\t\tconst char *dead = pid < 0 ? \" (with error)\" : \"\";\n-\n-\t\tif (pid < 0)\n-\t\t\tpid = -pid;\n-\n-\t\t/* XXX: Custom logging, since we don't wanna getpid() */\n-\t\tif (verbose) {\n-\t\t\tif (log_syslog)\n-\t\t\t\tsyslog(LOG_INFO, \"[%d] Disconnected%s\",\n-\t\t\t\t\t\tpid, dead);\n-\t\t\telse\n-\t\t\t\tfprintf(stderr, \"[%d] Disconnected%s\\n\",\n-\t\t\t\t\t\tpid, dead);\n-\t\t}\n-\t\tremove_child(pid, deleted, spawned);\n-\t\tdeleted++;\n+\t\tfor (; (next = blanket->next); blanket = next)\n+\t\t\tif (!memcmp(&blanket->address, &next->address,\n+\t\t\t\t   sizeof next->address)) {\n+\t\t\t\tkill(blanket->pid, SIGTERM);\n+\t\t\t\tbreak;\n+\t\t\t}\n \t}\n-\tchildren_deleted = deleted;\n }\n \n-static void check_max_connections(void)\n+static void check_dead_children(void)\n {\n-\tfor (;;) {\n-\t\tint active;\n-\t\tunsigned spawned, deleted;\n-\n-\t\tcheck_dead_children();\n-\n-\t\tspawned = children_spawned;\n-\t\tdeleted = children_deleted;\n-\n-\t\tactive = spawned - deleted;\n-\t\tif (active <= max_connections)\n-\t\t\tbreak;\n-\n-\t\t/* Kill some unstarted connections with SIGTERM */\n-\t\tkill_some_children(SIGTERM, deleted, spawned);\n-\t\tif (active <= max_connections << 1)\n-\t\t\tbreak;\n+\tint status;\n+\tpid_t pid;\n \n-\t\t/* If the SIGTERM thing isn't helping use SIGKILL */\n-\t\tkill_some_children(SIGKILL, deleted, spawned);\n-\t\tsleep(1);\n+\twhile ((pid = waitpid(-1, &status, WNOHANG))>0) {\n+\t\tconst char *dead = \"\";\n+\t\tremove_child(pid);\n+\t\tif (!WIFEXITED(status) || WEXITSTATUS(status) > 0)\n+\t\t\tdead = \" (with error)\";\n+\t\tloginfo(\"[%d] Disconnected%s\", (int)pid, dead);\n \t}\n }\n \n static void handle(int incoming, struct sockaddr *addr, int addrlen)\n {\n-\tpid_t pid = fork();\n+\tpid_t pid;\n \n-\tif (pid) {\n-\t\tunsigned idx;\n+\tif (max_connections && live_children >= max_connections) {\n+\t\tkill_some_child();\n+\t\tsleep(1);\t\t\t /* give it some time to die */\n+\t\tcheck_dead_children();\n+\t\tif (live_children >= max_connections) {\n+\t\t\tclose(incoming);\n+\t\t\tlogerror(\"Too many children, dropping connection\");\n+\t\t\treturn;\n+\t\t}\n+\t}\n \n+\tif ((pid = fork())) {\n \t\tclose(incoming);\n-\t\tif (pid < 0)\n+\t\tif (pid < 0) {\n+\t\t\tlogerror(\"Couldn't fork %s\", strerror(errno));\n \t\t\treturn;\n+\t\t}\n \n-\t\tidx = children_spawned % MAX_CHILDREN;\n-\t\tchildren_spawned++;\n-\t\tadd_child(idx, pid, addr, addrlen);\n-\n-\t\tcheck_max_connections();\n+\t\tadd_child(pid, addr, addrlen);\n \t\treturn;\n \t}\n \n@@ -1077,6 +1008,12 @@ int main(int argc, char **argv)\n \t\t\tinit_timeout = atoi(arg+15);\n \t\t\tcontinue;\n \t\t}\n+\t\tif (!prefixcmp(arg, \"--max-connections=\")) {\n+\t\t\tmax_connections = atoi(arg+18);\n+\t\t\tif (max_connections < 0)\n+\t\t\t\tmax_connections = 0;\t        /* unlimited */\n+\t\t\tcontinue;\n+\t\t}\n \t\tif (!strcmp(arg, \"--strict-paths\")) {\n \t\t\tstrict_paths = 1;\n \t\t\tcontinue;\n"},{"id":"87216","messageId":"20080814180220.15729.34048.stgit@aristoteles.cuci.nl","threadId":"15009","inReplyTo":null,"subject":"[PATCH 1/4] git-daemon: call logerror() instead of error()","fromName":"Stephen R. van den Berg","fromEmail":"srb@cuci.nl","sentAt":"2008-08-14T18:02:20Z","receivedAt":"2008-08-14T18:02:20Z","isPatch":true,"sender":{"key":"srb@cuci.nl","avatar":"https://gravatar.com/avatar/f75389059e827634d38e9df2a9b6ecbd50028b5a454442efa1c7205b7ff29c6a?d=mp&s=160"},"body":"Fix wording/case of the two messages.\n\nSigned-off-by: Stephen R. van den Berg <srb@cuci.nl>\n---\n\n daemon.c |    4 ++--\n 1 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex 8dcde73..93e1106 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -836,7 +836,7 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)\n \t\tif (sockfd < 0)\n \t\t\tcontinue;\n \t\tif (sockfd >= FD_SETSIZE) {\n-\t\t\terror(\"too large socket descriptor.\");\n+\t\t\tlogerror(\"Socket descriptor too large\");\n \t\t\tclose(sockfd);\n \t\t\tcontinue;\n \t\t}\n@@ -955,7 +955,7 @@ static int service_loop(int socknum, int *socklist)\n \n \t\tif (poll(pfd, socknum + 1, -1) < 0) {\n \t\t\tif (errno != EINTR) {\n-\t\t\t\terror(\"poll failed, resuming: %s\",\n+\t\t\t\tlogerror(\"Poll failed, resuming: %s\",\n \t\t\t\t      strerror(errno));\n \t\t\t\tsleep(1);\n \t\t\t}\n"}]}