summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Yao <ryao@gentoo.org>2012-11-18 02:15:16 -0500
committerRichard Yao <ryao@cs.stonybrook.edu>2012-12-08 09:48:07 -0500
commitbfc850a01b7ba1d961e2f32550c6871ddef909d9 (patch)
tree3757dcc0bd26a21588ed91f00abf767022b167c6
parent551346ef4d0afc9a376762ac7cb70121c12be920 (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.ac5
-rw-r--r--src/udev/udev-ctrl.c22
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");