@matheusbsbs / matheus-bagliano / commits / a5a9126bb4
Fork 0

git daemon: avoid calling syslog() from a signal handler

Signal handlers should never call syslog(), as that can raise signals of its own. Instead, call the syslog() from the master process. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Jul 3, 2008 at 16:27 UTC a5a9126bb4d7c2c23b94101dc49bcca33b6b17e8
1 file changed +50 -20
daemon.c
+50 -20
@@ -694,23 +694,47 @@ static void kill_some_children(int signo, unsigned start, unsigned stop)
694 }
695 }
696
697 +static void check_dead_children(void)
698 +{
699 + unsigned spawned, reaped, deleted;
700 +
701 + spawned = children_spawned;
702 + reaped = children_reaped;
703 + deleted = children_deleted;
704 +
705 + while (deleted < reaped) {
706 + pid_t pid = dead_child[deleted % MAX_CHILDREN];
707 + const char *dead = pid < 0 ? " (with error)" : "";
708 +
709 + if (pid < 0)
710 + pid = -pid;
711 +
712 + /* XXX: Custom logging, since we don't wanna getpid() */
713 + if (verbose) {
714 + if (log_syslog)
715 + syslog(LOG_INFO, "[%d] Disconnected%s",
716 + pid, dead);
717 + else
718 + fprintf(stderr, "[%d] Disconnected%s\n",
719 + pid, dead);
720 + }
721 + remove_child(pid, deleted, spawned);
722 + deleted++;
723 + }
724 + children_deleted = deleted;
725 +}
726 +
727 static void check_max_connections(void)
728 {
729 for (;;) {
730 int active;
701 - unsigned spawned, reaped, deleted;
731 + unsigned spawned, deleted;
732 +
733 + check_dead_children();
734
735 spawned = children_spawned;
704 - reaped = children_reaped;
736 deleted = children_deleted;
737
707 - while (deleted < reaped) {
708 - pid_t pid = dead_child[deleted % MAX_CHILDREN];
709 - remove_child(pid, deleted, spawned);
710 - deleted++;
711 - }
712 - children_deleted = deleted;
713 -
738 active = spawned - deleted;
739 if (active <= max_connections)
740 break;
@@ -760,18 +784,10 @@ static void child_handler(int signo)
784
785 if (pid > 0) {
786 unsigned reaped = children_reaped;
787 + if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)
788 + pid = -pid;
789 dead_child[reaped % MAX_CHILDREN] = pid;
790 children_reaped = reaped + 1;
765 - /* XXX: Custom logging, since we don't wanna getpid() */
766 - if (verbose) {
767 - const char *dead = "";
768 - if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)
769 - dead = " (with error)";
770 - if (log_syslog)
771 - syslog(LOG_INFO, "[%d] Disconnected%s", pid, dead);
772 - else
773 - fprintf(stderr, "[%d] Disconnected%s\n", pid, dead);
774 - }
791 continue;
792 }
793 break;
@@ -928,8 +944,18 @@ static int service_loop(int socknum, int *socklist)
944
945 for (;;) {
946 int i;
947 + int timeout;
948
932 - if (poll(pfd, socknum, -1) < 0) {
949 + /*
950 + * This 1-sec timeout could lead to idly looping but it is
951 + * here so that children culled in child_handler() are reported
952 + * without too much delay. We could probably set up a pipe
953 + * to ourselves that we poll, and write to the fd from child_handler()
954 + * to wake us up (and consume it when the poll() returns...
955 + */
956 + timeout = (children_spawned != children_deleted) ? 1000 : -1;
957 + i = poll(pfd, socknum, timeout);
958 + if (i < 0) {
959 if (errno != EINTR) {
960 error("poll failed, resuming: %s",
961 strerror(errno));
@@ -937,6 +963,10 @@ static int service_loop(int socknum, int *socklist)
963 }
964 continue;
965 }
966 + if (i == 0) {
967 + check_dead_children();
968 + continue;
969 + }
970
971 for (i = 0; i < socknum; i++) {
972 if (pfd[i].revents & POLLIN) {