connection on a rarely-accessed listening socket will cause a
child to hold the accept mutex and block out new connections until
another connection arrives on that rarely-accessed listening socket.
With Apache 2.x there is no performance concern about enabling the
logic for platforms which don't need it, so it is enabled everywhere
except for Win32.
Submitted by: Jeff Trawick
Reviewed by: Jim Jagielski, Justin Erenkrantz
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/APACHE_2_0_BRANCH@103018
13f79535-47bb-0310-9956-
ffa450edef68
Changes with Apache 2.0.49
+ *) SECURITY: CAN-2004-0174 (cve.mitre.org)
+ Fix starvation issue on listening sockets where a short-lived
+ connection on a rarely-accessed listening socket will cause a
+ child to hold the accept mutex and block out new connections until
+ another connection arrives on that rarely-accessed listening socket.
+ With Apache 2.x there is no performance concern about enabling the
+ logic for platforms which don't need it, so it is enabled everywhere
+ except for Win32. [Jeff Trawick]
+
*) mod_cgid: Fix storage corruption caused by use of incorrect pool.
[Jeff Trawick]
;;
esac
+APR_SETVAR(AP_NONBLOCK_WHEN_MULTI_LISTEN, [1])
+
dnl
dnl Process command line arguments. This is done early in the process so the
dnl user can get feedback quickly in case of an error.
[This platform doesn't suffer from the thundering herd problem])
fi
+if test "$AP_NONBLOCK_WHEN_MULTI_LISTEN" = "1"; then
+ AC_DEFINE(AP_NONBLOCK_WHEN_MULTI_LISTEN, 1,
+ [Listening sockets are non-blocking when there are more than 1])
+fi
+
AC_DEFINE_UNQUOTED(AP_SIG_GRACEFUL, SIG$AP_SIG_GRACEFUL, [Signal used to gracefully restart])
AC_DEFINE_UNQUOTED(AP_SIG_GRACEFUL_STRING, "SIG$AP_SIG_GRACEFUL", [Signal used to gracefully restart (as a quoted string)])
AC_DEFINE_UNQUOTED(AP_SIG_GRACEFUL_SHORT, $AP_SIG_GRACEFUL, [Signal used to gracefully restart (without SIG prefix)])
#include "ap_config_auto.h"
#include "ap_config_layout.h"
#endif
+#if defined(NETWARE)
+#define AP_NONBLOCK_WHEN_MULTI_LISTEN 1
+#endif
/* TODO - We need to put OS detection back to make all the following work */
#endif
#ifdef ENETUNREACH
case ENETUNREACH:
+#endif
+ /* EAGAIN/EWOULDBLOCK can be returned on BSD-derived
+ * TCP stacks when the connection is aborted before
+ * we call connect, but only because our listener
+ * sockets are non-blocking (AP_NONBLOCK_WHEN_MULTI_LISTEN)
+ */
+#ifdef EAGAIN
+ case EAGAIN:
+#endif
+#ifdef EWOULDBLOCK
+#if !defined(EAGAIN) || EAGAIN != EWOULDBLOCK
+ case EWOULDBLOCK:
+#endif
#endif
break;
#ifdef ENETDOWN
}
old_listeners = NULL;
+#if AP_NONBLOCK_WHEN_MULTI_LISTEN
+ /* if multiple listening sockets, make them non-blocking so that
+ * if select()/poll() reports readability for a reset connection that
+ * is already forgotten about by the time we call accept, we won't
+ * be hung until another connection arrives on that port
+ */
+ if (ap_listeners->next) {
+ for (lr = ap_listeners; lr; lr = lr->next) {
+ apr_status_t status;
+
+ status = apr_socket_opt_set(lr->sd, APR_SO_NONBLOCK, 1);
+ if (status != APR_SUCCESS) {
+ ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, status, pool,
+ "ap_listen_open: unable to make socket non-blocking");
+ return -1;
+ }
+ }
+ }
+#endif /* AP_NONBLOCK_WHEN_MULTI_LISTEN */
+
/* we come through here on both passes of the open logs phase
* only register the cleanup once... otherwise we try to close
* listening sockets twice when cleaning up prior to exec
if (sockdes > listenmaxfd) {
listenmaxfd = sockdes;
}
- /* Use non-blocking listen sockets so that we
- never get hung up. */
- apr_socket_opt_set(lr->sd, APR_SO_NONBLOCK, 1);
}
return 0;
}