summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--include/rpc/clnt.h12
-rw-r--r--include/sys/socket.h8
-rw-r--r--nis/ypclnt.c17
-rw-r--r--nptl/ChangeLog13
-rw-r--r--nptl/sysdeps/unix/sysv/linux/mq_notify.c29
-rw-r--r--socket/Makefile2
-rw-r--r--socket/have_sock_cloexec.c24
-rw-r--r--sunrpc/Versions3
-rw-r--r--sunrpc/clnt_udp.c60
10 files changed, 169 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index c46770a8ff..56c0415cc9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2008-07-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* include/rpc/clnt.h: Declare __libc_clntudp_bufcreate and
+	__libc_clntudp_bufcreate_internal.
+	* include/sys/socket.h: Declare __have_sock_cloexec.
+	* socket/Makefile (aux): Add have_sock_cloexec.
+	* socket/have_sock_cloexec.c: New file.
+	* sunrpc/clnt_udp.h (clntudp_bufcreate): Now a wrapper around
+	__libc_clntudp_bufcreate.
+	(__libc_clntudp_bufcreate): Former implementation of clntudp_bufcreate
+	which takes an additional parameter.  Create socket with non-blocking
+	mode and close-on-exec flag set, if wanted.
+	* sunrpc/Versions: Export __libc_clntudp_bufcreate@GLIBC_PRIVATE.
+	* nis/ypclnt.c (yp_bind_client_create): Use __libc_clntpudp_bufcreate
+	instead of clntudp_create.  The socket has already the close-on-exec
+	flag set if SOCK_CLOEXEC is defined.
+
 2008-07-24  Ulrich Drepper  <drepper@redhat.com>
 
 	* sysdeps/unix/sysv/linux/kernel-features.h: Define
diff --git a/include/rpc/clnt.h b/include/rpc/clnt.h
index 1e72e22bcb..75d88a65ca 100644
--- a/include/rpc/clnt.h
+++ b/include/rpc/clnt.h
@@ -21,6 +21,18 @@ extern CLIENT *clntudp_bufcreate_internal (struct sockaddr_in *__raddr,
 					   struct timeval __wait_resend,
 					   int *__sockp, u_int __sendsz,
 					   u_int __recvsz) attribute_hidden;
+extern CLIENT *__libc_clntudp_bufcreate (struct sockaddr_in *__raddr,
+					 u_long __program, u_long __version,
+					 struct timeval __wait_resend,
+					 int *__sockp, u_int __sendsz,
+					 u_int __recvsz, int __flags);
+extern CLIENT *__libc_clntudp_bufcreate_internal (struct sockaddr_in *__raddr,
+						  u_long __program,
+						  u_long __version,
+						  struct timeval __wait_resend,
+						  int *__sockp, u_int __sendsz,
+						  u_int __recvsz, int __flags)
+  attribute_hidden;
 extern CLIENT *clntunix_create_internal (struct sockaddr_un *__raddr,
 					 u_long __program, u_long __version,
 					 int *__sockp, u_int __sendsz,
diff --git a/include/sys/socket.h b/include/sys/socket.h
index 0a226726aa..df892783a0 100644
--- a/include/sys/socket.h
+++ b/include/sys/socket.h
@@ -153,4 +153,12 @@ extern int __libc_sa_len_internal (sa_family_t __af) attribute_hidden;
 # define __connect(fd, addr, len) INTUSE(__connect) (fd, addr, len)
 #endif
 
+#ifdef SOCK_CLOEXEC
+extern int __have_sock_cloexec;
+/* At lot of other functionality became available at the same time as
+   SOCK_CLOEXEC.  Avoid defining separate variables for all of them
+   unless it is really necessary.  */
+# define __have_paccept __have_sock_cloexec
+#endif
+
 #endif
diff --git a/nis/ypclnt.c b/nis/ypclnt.c
index 7d0091bd26..aaf4eb6e59 100644
--- a/nis/ypclnt.c
+++ b/nis/ypclnt.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2001, 2002, 2003, 2004, 2005, 2006
+/* Copyright (C) 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
@@ -28,6 +28,7 @@
 #include <rpcsvc/yp.h>
 #include <rpcsvc/ypclnt.h>
 #include <rpcsvc/ypupd.h>
+#include <sys/socket.h>
 #include <sys/uio.h>
 #include <bits/libc-lock.h>
 
@@ -69,14 +70,24 @@ yp_bind_client_create (const char *domain, dom_binding *ysd,
   ysd->dom_domain[YPMAXDOMAIN] = '\0';
 
   ysd->dom_socket = RPC_ANYSOCK;
-  ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
-				    UDPTIMEOUT, &ysd->dom_socket);
+#ifdef SOCK_CLOEXEC
+# define xflags SOCK_CLOEXEC
+#else
+# define xflags 0
+#endif
+  ysd->dom_client = __libc_clntudp_bufcreate (&ysd->dom_server_addr, YPPROG,
+					      YPVERS, UDPTIMEOUT,
+					      &ysd->dom_socket,
+					      UDPMSGSIZE, UDPMSGSIZE,
+					      xflags);
 
   if (ysd->dom_client != NULL)
     {
+#ifndef SOCK_CLOEXEC
       /* If the program exits, close the socket */
       if (fcntl (ysd->dom_socket, F_SETFD, FD_CLOEXEC) == -1)
 	perror ("fcntl: F_SETFD");
+#endif
     }
 }
 
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 744f90d786..27ced1aedb 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,14 @@
+2008-07-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/unix/sysv/linux/mq_notify.c (init_mq_netlink): Use
+	SOCK_CLOEXEC if possible.
+
+2008-05-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile (tests): Add tst-rwlock2a.
+	* tst-rwlock2.c: Use TYPE macro to decide what rwlock type to use.
+	* tst-rwlock2a.c: New file.
+
 2008-06-12  Ulrich Drepper  <drepper@redhat.com>
 
 	* sysdeps/pthread/pthread.h: Remove inadvertant checkin.
@@ -76,7 +87,7 @@
 
 2008-03-27  Ulrich Drepper  <drepper@redhat.com>
 
-	* sysdeps/unix/sysv/linux/bits/local_lim.h: Undefined ARG_MAX if
+	* sysdeps/unix/sysv/linux/bits/local_lim.h: Undefine ARG_MAX if
 	<linux/limits.h> has defined it.
 	* sysdeps/unix/sysv/linux/alpha/bits/local_lim.h: Likewise.
 	* sysdeps/unix/sysv/linux/ia64/bits/local_lim.h: Likewise.
diff --git a/nptl/sysdeps/unix/sysv/linux/mq_notify.c b/nptl/sysdeps/unix/sysv/linux/mq_notify.c
index 2ec11bf686..1be452a0e0 100644
--- a/nptl/sysdeps/unix/sysv/linux/mq_notify.c
+++ b/nptl/sysdeps/unix/sysv/linux/mq_notify.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contribute by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -29,6 +29,7 @@
 #include <unistd.h>
 #include <sys/socket.h>
 #include <not-cancel.h>
+#include <kernel-features.h>
 
 
 #ifdef __NR_mq_notify
@@ -152,18 +153,40 @@ reset_once (void)
 static void
 init_mq_netlink (void)
 {
+#ifdef SOCK_CLOEXEC
+# ifndef __ASSUME_SOCK_CLOEXEC
+  static int have_sock_cloexec;
+# else
+#  define have_sock_cloexec 1
+# endif
+#else
+# define have_sock_cloexec -1
+# define SOCK_CLOEXEC 0
+#endif
+
   /* This code might be called a second time after fork().  The file
      descriptor is inherited from the parent.  */
   if (netlink_socket == -1)
     {
       /* Just a normal netlink socket, not bound.  */
-      netlink_socket = socket (AF_NETLINK, SOCK_RAW, 0);
+      if (have_sock_cloexec)
+	{
+	  netlink_socket = socket (AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, 0);
+#if defined SOCK_CLOEXEC && !defined __ASSUME_SOCK_CLOEXEC
+	  if (have_sock_cloexec == 0)
+	    have_sock_cloexec = (netlink_socket != -1 || errno != EINVAL
+				 ? 1 : -1);
+#endif
+	}
+      if (have_sock_cloexec < 0)
+	netlink_socket = socket (AF_NETLINK, SOCK_RAW, 0);
       /* No need to do more if we have no socket.  */
       if (netlink_socket == -1)
 	return;
 
       /* Make sure the descriptor is closed on exec.  */
-      if (fcntl (netlink_socket, F_SETFD, FD_CLOEXEC) != 0)
+      if (have_sock_cloexec < 0
+	  && fcntl (netlink_socket, F_SETFD, FD_CLOEXEC) != 0)
 	goto errout;
     }
 
diff --git a/socket/Makefile b/socket/Makefile
index e1c9ec0fad..e7fa589e65 100644
--- a/socket/Makefile
+++ b/socket/Makefile
@@ -29,6 +29,8 @@ routines := accept bind connect getpeername getsockname getsockopt	\
 	    setsockopt shutdown socket socketpair isfdtype opensock	\
 	    sockatmark paccept
 
+aux	 := have_sock_cloexec
+
 distribute := ifreq.h
 
 include ../Rules
diff --git a/socket/have_sock_cloexec.c b/socket/have_sock_cloexec.c
new file mode 100644
index 0000000000..22dccdf722
--- /dev/null
+++ b/socket/have_sock_cloexec.c
@@ -0,0 +1,24 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sys/socket.h>
+#include <kernel-features.h>
+
+#if defined SOCK_CLOEXEC && !defined __ASSUME_SOCK_CLOEXEC
+int __have_sock_cloexec;
+#endif
diff --git a/sunrpc/Versions b/sunrpc/Versions
index cddf188766..d2d8e81ac0 100644
--- a/sunrpc/Versions
+++ b/sunrpc/Versions
@@ -116,4 +116,7 @@ libc {
   GLIBC_2.3.4 {
     xdr_quad_t; xdr_u_quad_t;
   }
+  GLIBC_PRIVATE {
+    __libc_clntudp_bufcreate;
+  }
 }
diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c
index 634313211d..e3a68129ec 100644
--- a/sunrpc/clnt_udp.c
+++ b/sunrpc/clnt_udp.c
@@ -54,12 +54,15 @@ static char sccsid[] = "@(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";
 #ifdef USE_IN_LIBIO
 # include <wchar.h>
 #endif
+#include <fcntl.h>
 
 #ifdef IP_RECVERR
 #include <errqueue.h>
 #include <sys/uio.h>
 #endif
 
+#include <kernel-features.h>
+
 extern bool_t xdr_opaque_auth (XDR *, struct opaque_auth *);
 extern u_long _create_xid (void);
 
@@ -121,9 +124,9 @@ struct cu_data
  * sent and received.
  */
 CLIENT *
-clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version,
-		   struct timeval wait, int *sockp, u_int sendsz,
-		   u_int recvsz)
+__libc_clntudp_bufcreate (struct sockaddr_in *raddr, u_long program,
+			  u_long version, struct timeval wait, int *sockp,
+			  u_int sendsz, u_int recvsz, int flags)
 {
   CLIENT *cl;
   struct cu_data *cu = NULL;
@@ -178,8 +181,32 @@ clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version,
     {
       int dontblock = 1;
 
-      *sockp = __socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-      if (*sockp < 0)
+#ifdef SOCK_NONBLOCK
+# ifndef __ASSUME_SOCK_CLOEXEC
+      if (__have_sock_cloexec >= 0)
+# endif
+	{
+	  *sockp = __socket (AF_INET, SOCK_DGRAM|SOCK_NONBLOCK|flags,
+			     IPPROTO_UDP);
+# ifndef __ASSUME_SOCK_CLOEXEC
+	  if (__have_sock_cloexec == 0)
+	    __have_sock_cloexec = *sockp >= 0 || errno != EINVAL ? 1 : -1;
+# endif
+	}
+#endif
+#ifndef __ASSUME_SOCK_CLOEXEC
+# ifdef SOCK_CLOEXEC
+      if (__have_sock_cloexec < 0)
+# endif
+	{
+	  *sockp = __socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+# ifdef SOCK_CLOEXEC
+	  if (flags & SOCK_CLOEXEC)
+	    fcntl (*sockp, F_SETFD, FD_CLOEXEC);
+# endif
+	}
+#endif
+      if (__builtin_expect (*sockp < 0, 0))
 	{
 	  struct rpc_createerr *ce = &get_rpc_createerr ();
 	  ce->cf_stat = RPC_SYSTEMERROR;
@@ -188,8 +215,13 @@ clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version,
 	}
       /* attempt to bind to prov port */
       (void) bindresvport (*sockp, (struct sockaddr_in *) 0);
-      /* the sockets rpc controls are non-blocking */
-      (void) __ioctl (*sockp, FIONBIO, (char *) &dontblock);
+#ifndef __ASSUME_SOCK_CLOEXEC
+# ifdef SOCK_CLOEXEC
+      if (__have_sock_cloexec < 0)
+# endif
+	/* the sockets rpc controls are non-blocking */
+	(void) __ioctl (*sockp, FIONBIO, (char *) &dontblock);
+#endif
 #ifdef IP_RECVERR
       {
 	int on = 1;
@@ -212,6 +244,16 @@ fooy:
     mem_free ((caddr_t) cl, sizeof (CLIENT));
   return (CLIENT *) NULL;
 }
+INTDEF (__libc_clntudp_bufcreate)
+
+CLIENT *
+clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version,
+		   struct timeval wait, int *sockp, u_int sendsz,
+		   u_int recvsz)
+{
+  return INTUSE(__libc_clntudp_bufcreate) (raddr, program, version, wait,
+					   sockp, sendsz, recvsz, 0);
+}
 INTDEF (clntudp_bufcreate)
 
 CLIENT *
@@ -222,8 +264,8 @@ clntudp_create (raddr, program, version, wait, sockp)
      struct timeval wait;
      int *sockp;
 {
-  return INTUSE(clntudp_bufcreate) (raddr, program, version, wait, sockp,
-				    UDPMSGSIZE, UDPMSGSIZE);
+  return INTUSE(__libc_clntudp_bufcreate) (raddr, program, version, wait,
+					   sockp, UDPMSGSIZE, UDPMSGSIZE, 0);
 }
 INTDEF (clntudp_create)