summaryrefslogtreecommitdiff
path: root/network_io
diff options
context:
space:
mode:
authorJeff Trawick <trawick@apache.org>2013-12-17 19:17:34 +0000
committerJeff Trawick <trawick@apache.org>2013-12-17 19:17:34 +0000
commit100101fd3f1e105144fec2cd7e81b8793cca2693 (patch)
treebe7191566488e66eeb47c6b2f988538f940558d4 /network_io
parent27f6f766211c6e14dea5c7c032284a91e01392a5 (diff)
downloadapr-100101fd3f1e105144fec2cd7e81b8793cca2693.tar.gz
Fix the inheritance of the non-blocking option across apr_socket_accept()
on FreeBSD 10 which was introduced with APR 1.5.0 through an unlikely mechanism: * FreeBSD 10 introduced accept4(). APR uses accept4() where it can find it. accept4() on Linux and FreeBSD 10 both have a SOCK_NONBLOCK flag, but on FreeBSD 10 the SOCK_NONBLOCK is the sole determiner of whether or not the connected socket is non-blocking. * clang is normally used on FreeBSD 10. * APR's configure-time check for inherited O_NONBLOCK didn't work with clang, so initially the lack of inheritance across accept4() wasn't a problem. * APR 1.5.0 allowed the configure-time check to work with clang, exposing the bad expectation about accept4() matching the accept() behavior. With FreeBSD accept4() (avail in 10+), O_NONBLOCK is not inherited (unlike Linux). Mimic the accept() behavior here in a way that may help other platforms as well. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1551659 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'network_io')
-rw-r--r--network_io/unix/sockets.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/network_io/unix/sockets.c b/network_io/unix/sockets.c
index 3c4dbe2f2..9fc774ed0 100644
--- a/network_io/unix/sockets.c
+++ b/network_io/unix/sockets.c
@@ -250,7 +250,20 @@ apr_status_t apr_socket_accept(apr_socket_t **new, apr_socket_t *sock,
sa.salen = sizeof(sa.sa);
#ifdef HAVE_ACCEPT4
- s = accept4(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen, SOCK_CLOEXEC);
+ {
+ int flags = SOCK_CLOEXEC;
+
+#if defined(SOCK_NONBLOCK) && APR_O_NONBLOCK_INHERITED
+ /* With FreeBSD accept4() (avail in 10+), O_NONBLOCK is not inherited
+ * (unlike Linux). Mimic the accept() behavior here in a way that
+ * may help other platforms.
+ */
+ if (apr_is_option_set(sock, APR_SO_NONBLOCK) == 1) {
+ flags |= SOCK_NONBLOCK;
+ }
+#endif
+ s = accept4(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen, flags);
+ }
#else
s = accept(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen);
#endif