aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--nscd/connections.c99
-rw-r--r--sysdeps/unix/sysv/linux/kernel-features.h9
3 files changed, 92 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog
index 67fc9d3..c46770a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2008-07-24 Ulrich Drepper <drepper@redhat.com>
+ * sysdeps/unix/sysv/linux/kernel-features.h: Define
+ __ASSUME_PACCEPT, __ASSUME_IN_NONBLOCK, and __ASSUME_PACCEPT if
+ appropriate.
+ * nscd/connections.c: Avoid fcntl calls to set close-on-exec flag and
+ non-blocking mode by using socket, paccept, and inotify_init1.
+
* Versions.def (glibc): Add GLIBC_2.9.
* io/Makefile (routines): Add dup3 and pipe2.
* io/Versions [glibc] (GLIBC_2.9): Add dup3 and pipe2.
diff --git a/nscd/connections.c b/nscd/connections.c
index e4d32b2..9b003cb 100644
--- a/nscd/connections.c
+++ b/nscd/connections.c
@@ -234,6 +234,14 @@ static int inotify_fd = -1;
static int resolv_conf_descr = -1;
#endif
+#ifndef __ASSUME_SOCK_CLOEXEC
+/* Negative if SOCK_CLOEXEC is not supported, positive if it is, zero
+ before be know the result. */
+static int have_sock_cloexec;
+/* The paccept syscall was introduced at the same time as SOCK_CLOEXEC. */
+# define have_paccept have_sock_cloexec
+#endif
+
/* Number of times clients had to wait. */
unsigned long int client_queued;
@@ -517,9 +525,15 @@ nscd_init (void)
#ifdef HAVE_INOTIFY
/* Use inotify to recognize changed files. */
- inotify_fd = inotify_init ();
- if (inotify_fd != -1)
- fcntl (inotify_fd, F_SETFL, O_NONBLOCK);
+ inotify_fd = inotify_init1 (IN_NONBLOCK);
+# ifndef __ASSUME_IN_NONBLOCK
+ if (inotify_fd == -1 && errno == ENOSYS)
+ {
+ inotify_fd = inotify_init ();
+ if (inotify_fd != -1)
+ fcntl (inotify_fd, F_SETFL, O_NONBLOCK);
+ }
+# endif
#endif
for (size_t cnt = 0; cnt < lastdb; ++cnt)
@@ -860,7 +874,21 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
}
/* Create the socket. */
- sock = socket (AF_UNIX, SOCK_STREAM, 0);
+#ifndef __ASSUME_SOCK_CLOEXEC
+ sock = -1;
+ if (have_sock_cloexec >= 0)
+#endif
+ {
+ sock = socket (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
+#ifdef __ASSUME_SOCK_CLOEXEC
+ if (have_sock_cloexec == 0)
+ have_sock_cloexec = sock != -1 || errno != EINVAL ? 1 : -1;
+#endif
+ }
+#ifndef __ASSUME_SOCK_CLOEXEC
+ if (have_sock_cloexec < 0)
+ sock = socket (AF_UNIX, SOCK_STREAM, 0);
+#endif
if (sock < 0)
{
dbg_log (_("cannot open socket: %s"), strerror (errno));
@@ -876,22 +904,27 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
exit (errno == EACCES ? 4 : 1);
}
- /* We don't want to get stuck on accept. */
- int fl = fcntl (sock, F_GETFL);
- if (fl == -1 || fcntl (sock, F_SETFL, fl | O_NONBLOCK) == -1)
+#ifndef __ASSUME_SOCK_CLOEXEC
+ if (have_sock_cloexec < 0)
{
- dbg_log (_("cannot change socket to nonblocking mode: %s"),
- strerror (errno));
- exit (1);
- }
+ /* We don't want to get stuck on accept. */
+ int fl = fcntl (sock, F_GETFL);
+ if (fl == -1 || fcntl (sock, F_SETFL, fl | O_NONBLOCK) == -1)
+ {
+ dbg_log (_("cannot change socket to nonblocking mode: %s"),
+ strerror (errno));
+ exit (1);
+ }
- /* The descriptor needs to be closed on exec. */
- if (paranoia && fcntl (sock, F_SETFD, FD_CLOEXEC) == -1)
- {
- dbg_log (_("cannot set socket to close on exec: %s"),
- strerror (errno));
- exit (1);
+ /* The descriptor needs to be closed on exec. */
+ if (paranoia && fcntl (sock, F_SETFD, FD_CLOEXEC) == -1)
+ {
+ dbg_log (_("cannot set socket to close on exec: %s"),
+ strerror (errno));
+ exit (1);
+ }
}
+#endif
/* Set permissions for the socket. */
chmod (_PATH_NSCDSOCKET, DEFFILEMODE);
@@ -1576,10 +1609,15 @@ nscd_run_worker (void *p)
/* We are done with the list. */
pthread_mutex_unlock (&readylist_lock);
- /* We do not want to block on a short read or so. */
- int fl = fcntl (fd, F_GETFL);
- if (fl == -1 || fcntl (fd, F_SETFL, fl | O_NONBLOCK) == -1)
- goto close_and_out;
+#ifndef __ASSUME_SOCK_CLOEXEC
+ if (have_sock_cloexec < 0)
+ {
+ /* We do not want to block on a short read or so. */
+ int fl = fcntl (fd, F_GETFL);
+ if (fl == -1 || fcntl (fd, F_SETFL, fl | O_NONBLOCK) == -1)
+ goto close_and_out;
+ }
+#endif
/* Now read the request. */
request_header req;
@@ -1779,7 +1817,24 @@ main_loop_poll (void)
if (conns[0].revents != 0)
{
/* We have a new incoming connection. Accept the connection. */
- int fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
+ int fd;
+
+#ifndef __ASSUME_PACCEPT
+ fd = -1;
+ if (have_paccept >= 0)
+#endif
+ {
+ fd = TEMP_FAILURE_RETRY (paccept (sock, NULL, NULL, NULL,
+ SOCK_NONBLOCK));
+#ifndef __ASSUME_PACCEPT
+ if (have_paccept == 0)
+ have_paccept = fd != -1 || errno != ENOSYS ? 1 : -1;
+#endif
+ }
+#ifndef __ASSUME_PACCEPT
+ if (have_paccept < 0)
+ fd = TEMP_FAILURE_RETRY (accept (sock, NULL, NULL));
+#endif
/* Use the descriptor if we have not reached the limit. */
if (fd >= 0)
diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index 5b41429..d595131 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -497,3 +497,12 @@
#if __LINUX_KERNEL_VERSION >= 0x02061b
# define __ASSUME_AT_EXECFN 1
#endif
+
+/* Support for various CLOEXEC and NONBLOCK flags was added for x86 and
+ x86-64 in 2.6.27. */
+#if __LINUX_KERNEL_VERSION >= 0x02061b \
+ && (defined __i386__ || defined __x86_64__)
+# define __ASSUME_SOCK_CLOEXEC 1
+# define __ASSUME_IN_NONBLOCK 1
+# define __ASSUME_PACCEPT 1
+#endif