about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2008-07-25 05:30:10 +0000
committerUlrich Drepper <drepper@redhat.com>2008-07-25 05:30:10 +0000
commit3ff2c948beaad303e376e1ad778d1cd8693a3099 (patch)
treed1e1056f73464e90f4462d7536b50ea07dc0b43e
parentbdcebfc4c7cc4f08efaf84af19465893f69fd5ed (diff)
downloadglibc-3ff2c948beaad303e376e1ad778d1cd8693a3099.tar.gz
glibc-3ff2c948beaad303e376e1ad778d1cd8693a3099.tar.xz
glibc-3ff2c948beaad303e376e1ad778d1cd8693a3099.zip
* 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.
-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 67fc9d3d1d..c46770a8ff 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 e4d32b27de..9b003cb2b0 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 5b41429f16..d5951317e4 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