SOCK_CLOEXEC is unsupported on linux kernel olders than 2.6.27

Joe Orton joe at manyfish.co.uk
Tue Jun 9 06:05:41 EDT 2009


On Thu, Mar 19, 2009 at 09:02:41AM +0100, Arkadiusz Miskiewicz wrote:
> SOCK_CLOEXEC is unsupported on linux kernel olders than 2.6.27. 
> Note that neon built with glibc that defines SOCK_CLOEXEC should
> be running on older kernels, too.

Thanks.  I've committed a slightly different fix, which persists the 
setting to avoid repeated failed socket() calls:

Index: src/ne_socket.c
===================================================================
--- src/ne_socket.c	(revision 1655)
+++ src/ne_socket.c	(revision 1657)
@@ -1,6 +1,6 @@
 /* 
    Socket handling routines
-   Copyright (C) 1998-2008, Joe Orton <joe at manyfish.co.uk>
+   Copyright (C) 1998-2009, Joe Orton <joe at manyfish.co.uk>
    Copyright (C) 1999-2000 Tommi Komulainen <Tommi.Komulainen at iki.fi>
    Copyright (C) 2004 Aleix Conchillo Flaque <aleix at member.fsf.org>
 
@@ -1286,19 +1286,31 @@
     }
 }
 
-#ifndef SOCK_CLOEXEC
-#define SOCK_CLOEXEC 0
-#define USE_CLOEXEC
+#ifdef SOCK_CLOEXEC
+/* sock_cloexec is initialized to SOCK_CLOEXEC and cleared to zero if
+ * a socket() call ever fails with EINVAL. */
+static int sock_cloexec = SOCK_CLOEXEC;
+#else
+#define sock_cloexec 0
 #endif
 
 int ne_sock_connect(ne_socket *sock,
                     const ne_inet_addr *addr, unsigned int port)
 {
     int fd, ret;
+    int type = SOCK_STREAM | sock_cloexec;
 
     /* use SOCK_STREAM rather than ai_socktype: some getaddrinfo
      * implementations do not set ai_socktype, e.g. RHL6.2. */
-    fd = socket(ia_family(addr), SOCK_STREAM | SOCK_CLOEXEC, ia_proto(addr));
+    fd = socket(ia_family(addr), type, ia_proto(addr));
+#ifdef SOCK_CLOEXEC
+    /* Handle forwards compat for new glibc on an older kernels; clear
+     * the sock_cloexec flag and retry the call: */
+    if (fd < 0 && sock_cloexec && errno == EINVAL) {
+        sock_cloexec = 0;
+        fd = socket(ia_family(addr), SOCK_STREAM, ia_proto(addr));
+    }
+#endif
     if (fd < 0) {
         set_strerror(sock, ne_errno);
 	return -1;
@@ -1313,9 +1325,10 @@
 #endif
    
 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) \
-  && defined(FD_CLOEXEC) && defined(USE_CLOEXEC)
-    /* Set the FD_CLOEXEC bit for the new fd. */
-    if ((ret = fcntl(fd, F_GETFD)) >= 0) {
+  && defined(FD_CLOEXEC)
+    /* Set the FD_CLOEXEC bit for the new fd, if the socket was not
+     * created with the CLOEXEC bit already set. */
+    if (!sock_cloexec && (ret = fcntl(fd, F_GETFD)) >= 0) {
         fcntl(fd, F_SETFD, ret | FD_CLOEXEC);
         /* ignore failure; not a critical error. */
     }




More information about the neon mailing list