diff options
author | Richard Yao <ryao@gentoo.org> | 2012-11-18 02:15:16 -0500 |
---|---|---|
committer | Richard Yao <ryao@cs.stonybrook.edu> | 2012-12-08 09:48:07 -0500 |
commit | bfc850a01b7ba1d961e2f32550c6871ddef909d9 (patch) | |
tree | 3757dcc0bd26a21588ed91f00abf767022b167c6 | |
parent | 551346ef4d0afc9a376762ac7cb70121c12be920 (diff) |
Add fallback path when accept4() is not available.
Commit ff2c503df091e6e4e9ab48cdb6df6ec8b7b525d0 introduced accept4() into
udev, which broke compatibility with kernels older than Linux 2.6.32 (or
Linux 2.6.36 on ARM). The purpose of accept4() is to permit
O_NONBLOCK and O_CLOEXEC to be specified at the accept() call site
while previously, they had to be set using fcntl() because Linux does
not inherit them.
Since accept4() increases the minimum kernel version, we add a fallback
path for situations in which it is unavailable.
Reported-by: Stephen Klimaszewski <steev@gentoo.org>
Signed-off-by: Richard Yao <ryao@gentoo.org>
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | src/udev/udev-ctrl.c | 22 |
2 files changed, 25 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac index ff9dacf218..59217a25ac 100644 --- a/configure.ac +++ b/configure.ac @@ -65,10 +65,11 @@ AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_UINT8_T -AC_CHECK_DECLS([gettid, pivot_root, name_to_handle_at], [], [], [[#include <sys/types.h> +AC_CHECK_DECLS([gettid, pivot_root, name_to_handle_at, accept4], [], [], [[#include <sys/types.h> #include <unistd.h> #include <sys/mount.h> -#include <fcntl.h>]]) +#include <fcntl.h> +#include <sys/socket.h>]]) # Checks for library functions. diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c index a235912ffb..c0c3fe5ae7 100644 --- a/src/udev/udev-ctrl.c +++ b/src/udev/udev-ctrl.c @@ -10,6 +10,7 @@ */ #include <errno.h> +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <stddef.h> @@ -188,7 +189,28 @@ struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl) conn->refcount = 1; conn->uctrl = uctrl; +#if HAVE_DECL_ACCEPT4 conn->sock = accept4(uctrl->sock, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK); + + /* Fallback path when accept4() is unavailable */ + if ( conn->sock < 0 && (errno == ENOSYS || errno == ENOTSUP) ) + { + conn->sock = accept(uctrl->sock, NULL, NULL); + + if (conn->sock >= 0) { + fcntl(conn->sock, F_SETFL, O_NONBLOCK); + fcntl(conn->sock, F_SETFD, FD_CLOEXEC); + } + } +#else + conn->sock = accept(uctrl->sock, NULL, NULL); + + if (conn->sock >= 0) { + fcntl(conn->sock, F_SETFL, O_NONBLOCK); + fcntl(conn->sock, F_SETFD, FD_CLOEXEC); + } +#endif + if (conn->sock < 0) { if (errno != EINTR) log_error("unable to receive ctrl connection: %m\n"); |