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 */