From bfc850a01b7ba1d961e2f32550c6871ddef909d9 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Sun, 18 Nov 2012 02:15:16 -0500 Subject: 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 Signed-off-by: Richard Yao --- configure.ac | 5 +++-- 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 +AC_CHECK_DECLS([gettid, pivot_root, name_to_handle_at, accept4], [], [], [[#include #include #include -#include ]]) +#include +#include ]]) # 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 +#include #include #include #include @@ -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"); -- cgit v1.2.3-54-g00ecf