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) {