dgaudet 98/02/16 17:45:59
Modified: src CHANGES http_main.c
Log:
Increase the robustness of the child_main loop. When unexpected
select() or accept() errors occur we exit() the child. This deals
with many reported problems where apache would fill the error_log
with messages.
PR: 1747, 1107, 588, 1787, 987, 588
Revision Changes Path
1.296 +5 -0 apache-1.2/src/CHANGES
Index: CHANGES
===================================================================
RCS file: /export/home/cvs/apache-1.2/src/CHANGES,v
retrieving revision 1.295
retrieving revision 1.296
diff -u -r1.295 -r1.296
--- CHANGES 1998/02/14 13:42:44 1.295
+++ CHANGES 1998/02/17 01:45:57 1.296
@@ -1,5 +1,10 @@
Changes with Apache 1.2.6
+ *) Increase the robustness of the child_main loop. When unexpected
+ select() or accept() errors occur we exit() the child. This deals
+ with many reported problems where apache would fill the error_log
+ with messages. [Dean Gaudet] PR#1747, 1107, 588, 1787, 987, 588
+
*) PORT: Add -lm to LIBS for HPUX. [Dean Gaudet] PR#1639
*) SECURITY: "UserDir /abspath" without a * in the path would allow
1.151 +62 -15 apache-1.2/src/http_main.c
Index: http_main.c
===================================================================
RCS file: /export/home/cvs/apache-1.2/src/http_main.c,v
retrieving revision 1.150
retrieving revision 1.151
diff -u -r1.150 -r1.151
--- http_main.c 1998/01/30 09:13:55 1.150
+++ http_main.c 1998/02/17 01:45:58 1.151
@@ -1781,14 +1781,14 @@
errno = errsave;
if (srv < 0 && errno != EINTR) {
-#ifdef LINUX
- if (errno == EFAULT) {
- log_unixerr("select", "(listen) fatal, exiting",
- NULL, server_conf);
- exit(1);
- }
-#endif
+ /* Single Unix documents select as returning errnos
+ * EBADF, EINTR, and EINVAL... and in none of those
+ * cases does it make sense to continue. In fact
+ * on Linux 2.0.x we seem to end up with EFAULT
+ * occasionally, and we'd loop forever due to it.
+ */
log_unixerr("select", "(listen)", NULL, server_conf);
+ exit(1);
}
if (srv <= 0)
@@ -1819,15 +1819,62 @@
if (csd >= 0)
break; /* We have a socket ready for reading */
else {
-
-#if defined(EPROTO) && defined(ECONNABORTED)
- if ((errno != EPROTO) && (errno != ECONNABORTED))
-#elif defined(EPROTO)
- if (errno != EPROTO)
-#elif defined(ECONNABORTED)
- if (errno != ECONNABORTED)
+ /* Our old behaviour here was to continue after accept()
+ * errors. But this leads us into lots of troubles
+ * because most of the errors are quite fatal. For
+ * example, EMFILE can be caused by slow descriptor
+ * leaks (say in a 3rd party module, or libc). It's
+ * foolish for us to continue after an EMFILE. We also
+ * seem to tickle kernel bugs on some platforms which
+ * lead to never-ending loops here. So it seems best
+ * to just exit in most cases.
+ */
+ switch (errno) {
+#ifdef EPROTO
+ /* EPROTO on certain older kernels really means
+ * ECONNABORTED, so we need to ignore it for them.
+ * See discussion in new-httpd archives nh.9701
+ * search for EPROTO.
+ *
+ * Also see nh.9603, search for EPROTO:
+ * There is potentially a bug in Solaris 2.x x<6,
+ * and other boxes that implement tcp sockets in
+ * userland (i.e. on top of STREAMS). On these
+ * systems, EPROTO can actually result in a fatal
+ * loop. See PR#981 for example. It's hard to
+ * handle both uses of EPROTO.
+ */
+ case EPROTO:
+#endif
+#ifdef ECONNABORTED
+ case ECONNABORTED:
+#endif
+ /* Linux generates the rest of these, other tcp
+ * stacks (i.e. bsd) tend to hide them behind
+ * getsockopt() interfaces. They occur when
+ * the net goes sour or the client disconnects
+ * after the three-way handshake has been done
+ * in the kernel but before userland has picked
+ * up the socket.
+ */
+#ifdef ECONNRESET
+ case ECONNRESET:
#endif
- log_unixerr("accept", "(client socket)", NULL, server_conf);
+#ifdef ETIMEDOUT
+ case ETIMEDOUT:
+#endif
+#ifdef EHOSTUNREACH
+ case EHOSTUNREACH:
+#endif
+#ifdef ENETUNREACH
+ case ENETUNREACH:
+#endif
+ break;
+
+ default:
+ log_unixerr("accept", "(client socket)", NULL, server_conf);
+ exit(1);
+ }
}
/* go around again, safe to die */