On Thu, Jul 16, 2009 at 11:42:52AM +1000, Bojan Smojver wrote: > On Thu, 2009-07-16 at 01:39 +0000, bo...@apache.org wrote: > > Use more elaborate checks for epoll_create1, dup3 and accept4. > > This requires review folks. There is code in the tests that can > potentially hang the configure process. It does work on my Fedora 11 box > (which has the functions) and on RHEL4 (which doesn't have them), but it > would be really great to test this on other platforms, especially other > Linux flavours.
The accept4() configure test looks a bit overcomplicated; it would be possible to simplify a bit to avoid the fork etc, by creating a socket with SOCK_NONBLOCK set, and simply calling accept4() and presuming the syscall is wired up if it returns EAGAIN. But, on the issue of runtime/build-time feature detection: In the past I have argued we should never do runtime platform feature detection, i.e., if accept4() works at build-time, we can presume it works at run-time. I think I need to soften that position now; use of a modern userspace on an older kernel seems to be very widespread in Xen hosting sites. I shipped socket(,SOCK_CLOEXEC) support in neon and got lots of complaints, from users across the spectrum of distributions. So I fear we should probably do the same thing in APR. Any other opinions? (Debianites, feel free to send me the hate mail now ;) It would simplify the configure script, e.g. for accept4 support we could use simply AC_CHECK_FUNCS and change apr_socket_accept something like this (completely untested): Thoughts? Index: network_io/unix/sockets.c =================================================================== --- network_io/unix/sockets.c (revision 790537) +++ network_io/unix/sockets.c (working copy) @@ -230,14 +230,21 @@ apr_status_t apr_socket_accept(apr_socket_t **new, apr_socket_t *sock, apr_pool_t *connection_context) { - int s; + int s, flags; apr_sockaddr_t sa; sa.salen = sizeof(sa.sa); #ifdef HAVE_ACCEPT4 + /* Attempt to use accept4() but fall back on accept(). */ + flags = FD_CLOEXEC; s = accept4(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen, SOCK_CLOEXEC); + if (s < 0 && errno == ENOSYS) { + flags = 0; + s = accept(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen); + } #else + flags = 0; s = accept(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen); #endif @@ -321,10 +328,10 @@ (*new)->local_interface_unknown = 1; } -#ifndef HAVE_ACCEPT4 - { - int flags; - + /* Toggle the CLOEXEC bit on. Note that this will be done either + * if no accept4() support was present, or, if it was present but + * failed with ENOSYS. */ + if (flags == 0) { if ((flags = fcntl((*new)->socketdes, F_GETFD)) == -1) return errno; @@ -332,7 +339,6 @@ if (fcntl((*new)->socketdes, F_SETFD, flags) == -1) return errno; } -#endif (*new)->inherit = 0; apr_pool_cleanup_register((*new)->pool, (void *)(*new), socket_cleanup,