diff options
author | Jeff Trawick <trawick@apache.org> | 2013-12-17 19:17:34 +0000 |
---|---|---|
committer | Jeff Trawick <trawick@apache.org> | 2013-12-17 19:17:34 +0000 |
commit | 100101fd3f1e105144fec2cd7e81b8793cca2693 (patch) | |
tree | be7191566488e66eeb47c6b2f988538f940558d4 /network_io | |
parent | 27f6f766211c6e14dea5c7c032284a91e01392a5 (diff) | |
download | apr-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.c | 15 |
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 |