[PATCH] SOCK_CLOEXEC for opening sockets

Andrew Luo andrewluotechnologies at outlook.com
Thu Aug 30 17:32:01 UTC 2018


Just checking to see if anyone has any other comments/feedback on this.

Thanks,

-Andrew

-----Original Message-----
From: Andrew Luo 
Sent: Monday, July 30, 2018 9:44 PM
To: 'Andrew Luo' <andrewluotechnologies at outlook.com>; Ivan Gerasimov <ivan.gerasimov at oracle.com>; Chris Hegarty <chris.hegarty at oracle.com>
Cc: net-dev at openjdk.java.net
Subject: RE: [PATCH] SOCK_CLOEXEC for opening sockets

Fixed a bug, updated (I was calling accept directly instead of a helper function that calls accept then fcntl):

diff --git a/make/lib/Lib-jdk.net.gmk b/make/lib/Lib-jdk.net.gmk
--- a/make/lib/Lib-jdk.net.gmk
+++ b/make/lib/Lib-jdk.net.gmk
@@ -33,9 +33,11 @@
       NAME := extnet, \
       OPTIMIZATION := LOW, \
       CFLAGS := $(CFLAGS_JDKLIB), \
+      EXTRA_HEADER_DIRS := \
+          java.base:libnet, \
       LDFLAGS := $(LDFLAGS_JDKLIB) \
           $(call SET_SHARED_LIBRARY_ORIGIN), \
-      LIBS := -ljava, \
+      LIBS := -ljava -lnet, \
       LIBS_solaris := -lsocket, \
       LIBS_linux := -ljvm, \
   ))
diff --git a/src/java.base/aix/native/libnio/ch/AixPollPort.c b/src/java.base/aix/native/libnio/ch/AixPollPort.c
--- a/src/java.base/aix/native/libnio/ch/AixPollPort.c
+++ b/src/java.base/aix/native/libnio/ch/AixPollPort.c
@@ -30,6 +30,7 @@
 #include "jlong.h"
 
 #include "sun_nio_ch_AixPollPort.h"
+#include "net_util_md.h"
 
 #include <unistd.h>
 #include <sys/types.h>
@@ -137,7 +138,7 @@
 JNIEXPORT void JNICALL
 Java_sun_nio_ch_AixPollPort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
     int sp[2];
-    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
+    if (NET_SocketPair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
         JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
     } else {
         jint res[2];
diff --git a/src/java.base/linux/native/libnet/linux_close.c b/src/java.base/linux/native/libnet/linux_close.c
--- a/src/java.base/linux/native/libnet/linux_close.c
+++ b/src/java.base/linux/native/libnet/linux_close.c
@@ -24,6 +24,7 @@
  */
 
 #include <assert.h>
+#include <dlfcn.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -395,8 +396,32 @@
     BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );  }
 
-int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
-    BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
+static int acceptFcntlCloexec(int s, struct sockaddr *addr, socklen_t *addrlen) {
+    int cs;
+    cs = accept(s, addr, addrlen);
+    if (cs != -1) {
+        // Best effort - return value is intentionally ignored since the connected
+        // socket was successfully created.
+        fcntl(cs, F_SETFD, FD_CLOEXEC);
+    }
+    return cs;
+}
+
+JNIEXPORT int JNICALL
+NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
+    static int (*accept4functionpointer)(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) = NULL;
+    static int accept4initialized = 0;
+    int cs;
+
+    if (!accept4initialized) {
+        accept4functionpointer = dlsym(RTLD_DEFAULT, "accept4");
+        accept4initialized = 1;
+    }
+
+    if (accept4functionpointer != NULL) {
+        BLOCKING_IO_RETURN_INT( s, accept4functionpointer(s, addr, addrlen, SOCK_CLOEXEC) );
+    }
+    BLOCKING_IO_RETURN_INT( s, acceptFcntlCloexec(s, addr, addrlen) );
 }
 
 int NET_Connect(int s, struct sockaddr *addr, int addrlen) { diff --git a/src/java.base/unix/native/libnet/Inet4AddressImpl.c b/src/java.base/unix/native/libnet/Inet4AddressImpl.c
--- a/src/java.base/unix/native/libnet/Inet4AddressImpl.c
+++ b/src/java.base/unix/native/libnet/Inet4AddressImpl.c
@@ -264,7 +264,7 @@
     int connect_rv = -1;
 
     // open a TCP socket
-    fd = socket(AF_INET, SOCK_STREAM, 0);
+    fd = NET_Socket(AF_INET, SOCK_STREAM, 0);
     if (fd == -1) {
         // note: if you run out of fds, you may not be able to load
         // the exception class, and get a NoClassDefFoundError instead.
@@ -503,7 +503,7 @@
 
     // Let's try to create a RAW socket to send ICMP packets.
     // This usually requires "root" privileges, so it's likely to fail.
-    fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+    fd = NET_Socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
     if (fd == -1) {
         return tcp_ping4(env, &sa, netif, timeout, ttl);
     } else {
diff --git a/src/java.base/unix/native/libnet/Inet6AddressImpl.c b/src/java.base/unix/native/libnet/Inet6AddressImpl.c
--- a/src/java.base/unix/native/libnet/Inet6AddressImpl.c
+++ b/src/java.base/unix/native/libnet/Inet6AddressImpl.c
@@ -461,7 +461,7 @@
     int connect_rv = -1;
 
     // open a TCP socket
-    fd = socket(AF_INET6, SOCK_STREAM, 0);
+    fd = NET_Socket(AF_INET6, SOCK_STREAM, 0);
     if (fd == -1) {
         // note: if you run out of fds, you may not be able to load
         // the exception class, and get a NoClassDefFoundError instead.
@@ -711,7 +711,7 @@
 
     // Let's try to create a RAW socket to send ICMP packets.
     // This usually requires "root" privileges, so it's likely to fail.
-    fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+    fd = NET_Socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
     if (fd == -1) {
         return tcp_ping6(env, &sa, netif, timeout, ttl);
     } else {
diff --git a/src/java.base/unix/native/libnet/NetworkInterface.c b/src/java.base/unix/native/libnet/NetworkInterface.c
--- a/src/java.base/unix/native/libnet/NetworkInterface.c
+++ b/src/java.base/unix/native/libnet/NetworkInterface.c
@@ -1055,7 +1055,7 @@
 static int openSocket(JNIEnv *env, int proto) {
     int sock;
 
-    if ((sock = socket(proto, SOCK_DGRAM, 0)) < 0) {
+    if ((sock = NET_Socket(proto, SOCK_DGRAM, 0)) < 0) {
         // If EPROTONOSUPPORT is returned it means we don't have
         // support for this proto so don't throw an exception.
         if (errno != EPROTONOSUPPORT) { @@ -1078,9 +1078,9 @@  static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
     int sock;
 
-    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+    if ((sock = NET_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
         if (errno == EPROTONOSUPPORT) {
-            if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+            if ((sock = NET_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
                 JNU_ThrowByNameWithMessageAndLastError
                     (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
                 return -1;
@@ -1315,9 +1315,9 @@
 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
     int sock;
 
-    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+    if ((sock = NET_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
         if (errno == EPROTONOSUPPORT) {
-            if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+            if ((sock = NET_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
                 JNU_ThrowByNameWithMessageAndLastError
                     (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
                 return -1;
@@ -1590,9 +1590,9 @@
     int sock, alreadyV6 = 0;
     struct lifreq if2;
 
-    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+    if ((sock = NET_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
         if (errno == EPROTONOSUPPORT) {
-            if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+            if ((sock = NET_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
                 JNU_ThrowByNameWithMessageAndLastError
                     (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
                 return -1;
@@ -1616,7 +1616,7 @@
         strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
         if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
             close(sock);
-            if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+            if ((sock = NET_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
                 JNU_ThrowByNameWithMessageAndLastError
                     (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
                 return -1;
@@ -1941,9 +1941,9 @@
 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
     int sock;
 
-    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+    if ((sock = NET_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
         if (errno == EPROTONOSUPPORT) {
-            if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+            if ((sock = NET_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
                 JNU_ThrowByNameWithMessageAndLastError
                     (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
                 return -1;
diff --git a/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c b/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c
--- a/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c
+++ b/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c
@@ -904,7 +904,7 @@
         return;
     }
 
-    if ((fd = socket(domain, SOCK_DGRAM, 0)) == -1) {
+    if ((fd = NET_Socket(domain, SOCK_DGRAM, 0)) == -1) {
         JNU_ThrowByNameWithMessageAndLastError
             (env, JNU_JAVANETPKG "SocketException", "Error creating socket");
         return;
diff --git a/src/java.base/unix/native/libnet/PlainSocketImpl.c b/src/java.base/unix/native/libnet/PlainSocketImpl.c
--- a/src/java.base/unix/native/libnet/PlainSocketImpl.c
+++ b/src/java.base/unix/native/libnet/PlainSocketImpl.c
@@ -77,7 +77,7 @@
     int sv[2];
 
 #ifdef AF_UNIX
-    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
+    if (NET_SocketPair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
         return -1;
     }
 #else
@@ -178,7 +178,7 @@
         return;
     }
 
-    if ((fd = socket(domain, type, 0)) == -1) {
+    if ((fd = NET_Socket(domain, type, 0)) == -1) {
         /* note: if you run out of fds, you may not be able to load
          * the exception class, and get a NoClassDefFoundError
          * instead.
diff --git a/src/java.base/unix/native/libnet/SdpSupport.c b/src/java.base/unix/native/libnet/SdpSupport.c
--- a/src/java.base/unix/native/libnet/SdpSupport.c
+++ b/src/java.base/unix/native/libnet/SdpSupport.c
@@ -57,7 +57,7 @@
 
 #if defined(__solaris__)
     int domain = ipv6_available() ? AF_INET6 : AF_INET;
-    s = socket(domain, SOCK_STREAM, PROTO_SDP);
+    s = NET_Socket(domain, SOCK_STREAM, PROTO_SDP);
 #elif defined(__linux__)
     /**
      * IPv6 not supported by SDP on Linux @@ -66,7 +66,7 @@
         JNU_ThrowIOException(env, "IPv6 not supported");
         return -1;
     }
-    s = socket(AF_INET_SDP, SOCK_STREAM, 0);
+    s = NET_Socket(AF_INET_SDP, SOCK_STREAM, 0);
 #else
     /* not supported on other platforms at this time */
     s = -1;
diff --git a/src/java.base/unix/native/libnet/net_util_md.c b/src/java.base/unix/native/libnet/net_util_md.c
--- a/src/java.base/unix/native/libnet/net_util_md.c
+++ b/src/java.base/unix/native/libnet/net_util_md.c
@@ -131,6 +131,52 @@
     return (result == -1) ? 0 : 1;
 }
 
+ /*
+  * Creates a socket.
+  * Uses SOCK_CLOEXEC during creation or FD_CLOEXEC post-creation, 
+ where possible
+  * and on a best-effort basis, on systems that support it.
+  */
+ JNIEXPORT int JNICALL
+ NET_Socket(int domain, int type, int protocol) {
+     int s;
+ #if defined(SOCK_CLOEXEC)
+     s = socket(domain, type | SOCK_CLOEXEC, protocol);
+     if (s != -1 || (s == -1 && errno != EINVAL)) {
+         return s;
+     }
+ #endif
+     s = socket(domain, type, protocol);
+     if (s != -1) {
+         // Best effort - return value is intentionally ignored since the socket
+         // was successfully created.
+         fcntl(s, F_SETFD, FD_CLOEXEC);
+     }
+     return s;
+ }
+
+/*
+ * Creates a pair of connected sockets.
+ * Uses SOCK_CLOEXEC during creation or FD_CLOEXEC post-creation, where 
+possible
+ * and on a best-effort basis, on systems that support it.
+ */
+JNIEXPORT int JNICALL
+NET_SocketPair(int domain, int type, int protocol, int socket_vector[2]) {
+    int s;
+#if defined(SOCK_CLOEXEC)
+    s = socketpair(domain, type | SOCK_CLOEXEC, protocol, socket_vector);
+    if (s != -1 || (s == -1 && errno != EINVAL)) {
+        return s;
+    }
+#endif
+    s = socketpair(domain, type, protocol, socket_vector);
+    if (s != -1) {
+        // Best effort - return value is intentionally ignored since the socket
+        // was successfully created.
+        fcntl(s, F_SETFD, FD_CLOEXEC);
+    }
+    return s;
+}
+
 #ifdef __solaris__
 static int init_tcp_max_buf, init_udp_max_buf;  static int tcp_max_buf; @@ -295,7 +341,7 @@
     SOCKETADDRESS sa;
     socklen_t sa_len = sizeof(SOCKETADDRESS);
 
-    fd = socket(AF_INET6, SOCK_STREAM, 0) ;
+    fd = NET_Socket(AF_INET6, SOCK_STREAM, 0) ;
     if (fd < 0) {
         /*
          *  TODO: We really cant tell since it may be an unrelated error @@ -402,7 +448,7 @@
     /* Do a simple dummy call, and try to figure out from that */
     int one = 1;
     int rv, s;
-    s = socket(PF_INET, SOCK_STREAM, 0);
+    s = NET_Socket(PF_INET, SOCK_STREAM, 0);
     if (s < 0) {
         return JNI_FALSE;
     }
diff --git a/src/java.base/unix/native/libnet/net_util_md.h b/src/java.base/unix/native/libnet/net_util_md.h
--- a/src/java.base/unix/native/libnet/net_util_md.h
+++ b/src/java.base/unix/native/libnet/net_util_md.h
@@ -77,6 +77,9 @@
  * Functions
  */
 
+JNIEXPORT int JNICALL NET_Socket(int domain, int type, int protocol); 
+JNIEXPORT int JNICALL NET_SocketPair(int domain, int type, int 
+protocol, int socket_vector[2]);
+
 int NET_Timeout(JNIEnv *env, int s, long timeout, jlong  nanoTimeStamp);  int NET_Read(int s, void* buf, size_t len);  int NET_NonBlockingRead(int s, void* buf, size_t len); @@ -88,7 +91,7 @@
                flags, const struct sockaddr *to, int tolen);  int NET_Writev(int s, const struct iovec * vector, int count);  int NET_Connect(int s, struct sockaddr *addr, int addrlen); -int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+JNIEXPORT int JNICALL NET_Accept(int s, struct sockaddr *addr, 
+socklen_t *addrlen);
 int NET_SocketClose(int s);
 int NET_Dup2(int oldfd, int newfd);
 int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout); diff --git a/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c b/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c
--- a/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c
+++ b/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c
@@ -56,6 +56,7 @@
 #include "jlong.h"
 #include "nio.h"
 #include "nio_util.h"
+#include "net_util_md.h"
 #include "sun_nio_ch_FileDispatcherImpl.h"
 #include "java_lang_Long.h"
 
@@ -67,7 +68,7 @@
 Java_sun_nio_ch_FileDispatcherImpl_init(JNIEnv *env, jclass cl)  {
     int sp[2];
-    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) {
+    if (NET_SocketPair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) {
         JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
         return;
     }
diff --git a/src/java.base/unix/native/libnio/ch/Net.c b/src/java.base/unix/native/libnio/ch/Net.c
--- a/src/java.base/unix/native/libnio/ch/Net.c
+++ b/src/java.base/unix/native/libnio/ch/Net.c
@@ -198,7 +198,7 @@
     int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
     int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;
 
-    fd = socket(domain, type, 0);
+    fd = NET_Socket(domain, type, 0);
     if (fd < 0) {
         return handleSocketError(env, errno);
     }
diff --git a/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c b/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c
--- a/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c
+++ b/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c
@@ -92,7 +92,7 @@
      * accept() was called.
      */
     for (;;) {
-        newfd = accept(ssfd, &sa.sa, &sa_len);
+        newfd = NET_Accept(ssfd, &sa.sa, &sa_len);
         if (newfd >= 0) {
             break;
         }
diff --git a/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c b/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c
--- a/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c
+++ b/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c
@@ -31,6 +31,7 @@
 #include <netinet/tcp.h>
 #include <netinet/in.h>
 #include "jni_util.h"
+#include "net_util_md.h"
 #include "jdk_net_LinuxSocketOptions.h"
 
 /*
@@ -86,7 +87,7 @@
 (JNIEnv *env, jobject unused) {
     int one = 1;
     int rv, s;
-    s = socket(PF_INET, SOCK_STREAM, 0);
+    s = NET_Socket(PF_INET, SOCK_STREAM, 0);
     if (s < 0) {
         return JNI_FALSE;
     }
@@ -103,7 +104,7 @@
 static jint socketOptionSupported(jint sockopt) {
     jint one = 1;
     jint rv, s;
-    s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+    s = NET_Socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
     if (s < 0) {
         return 0;
     }
diff --git a/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c b/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c
--- a/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c
+++ b/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c
@@ -31,11 +31,12 @@
 #include <netinet/tcp.h>
 #include <netinet/in.h>
 #include "jni_util.h"
+#include "net_util_md.h"
 
 static jint socketOptionSupported(jint sockopt) {
     jint one = 1;
     jint rv, s;
-    s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+    s = NET_Socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
     if (s < 0) {
         return 0;
     }
diff --git a/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c b/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c
--- a/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c
+++ b/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c
@@ -157,7 +157,7 @@
     sock_flow_props_t props;
     int rv, s;
 
-    s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+    s = NET_Socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
     if (s < 0) {
         return JNI_FALSE;
     }
diff --git a/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h b/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h
--- a/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h
+++ b/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h
@@ -36,6 +36,7 @@
 #include "jdk_net_SocketFlow.h"
 #include "SolarisSocketOptions.h"
 #include "jdk_net_SolarisSocketOptions.h"
+#include "net_util_md.h"
 
 #ifndef SO_FLOW_SLA
 #define SO_FLOW_SLA 0x1018
diff --git a/src/jdk.sctp/unix/native/libsctp/SctpNet.c b/src/jdk.sctp/unix/native/libsctp/SctpNet.c
--- a/src/jdk.sctp/unix/native/libsctp/SctpNet.c
+++ b/src/jdk.sctp/unix/native/libsctp/SctpNet.c
@@ -151,7 +151,7 @@
 Java_sun_nio_ch_sctp_SctpNet_init
   (JNIEnv *env, jclass cl) {
     int sp[2];
-    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) {
+    if (NET_SocketPair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) {
         JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
         return;
     }
@@ -180,7 +180,7 @@
         return 0;
     }
 
-    fd = socket(domain, (oneToOne ? SOCK_STREAM : SOCK_SEQPACKET), IPPROTO_SCTP);
+    fd = NET_Socket(domain, (oneToOne ? SOCK_STREAM : SOCK_SEQPACKET), 
+ IPPROTO_SCTP);
 
     if (fd < 0) {
         return handleSocketError(env, errno);

Thanks,

-Andrew

-----Original Message-----
From: Andrew Luo <andrewluotechnologies at outlook.com>
Sent: Monday, July 30, 2018 5:08 PM
To: Andrew Luo <andrewluotechnologies at outlook.com>; Ivan Gerasimov <ivan.gerasimov at oracle.com>; Chris Hegarty <chris.hegarty at oracle.com>
Cc: net-dev at openjdk.java.net
Subject: RE: [PATCH] SOCK_CLOEXEC for opening sockets

I've updated my patch.  Let me know if this approach looks good to you.  I'm using dlsym to get the function pointer to accept4 at runtime so we can support compiling on newer Linux systems and using the binaries on older Linux systems (where the newer Linux system has accept4, and the older Linux system does not).  I know I still need to edit the other Unix (Solaris, AIX, BSD) files but I wanted to put this out there first to see if the approach looks good.

diff --git a/make/lib/Lib-jdk.net.gmk b/make/lib/Lib-jdk.net.gmk
--- a/make/lib/Lib-jdk.net.gmk
+++ b/make/lib/Lib-jdk.net.gmk
@@ -33,9 +33,11 @@
       NAME := extnet, \
       OPTIMIZATION := LOW, \
       CFLAGS := $(CFLAGS_JDKLIB), \
+      EXTRA_HEADER_DIRS := \
+          java.base:libnet, \
       LDFLAGS := $(LDFLAGS_JDKLIB) \
           $(call SET_SHARED_LIBRARY_ORIGIN), \
-      LIBS := -ljava, \
+      LIBS := -ljava -lnet, \
       LIBS_solaris := -lsocket, \
       LIBS_linux := -ljvm, \
   ))
diff --git a/src/java.base/aix/native/libnio/ch/AixPollPort.c b/src/java.base/aix/native/libnio/ch/AixPollPort.c
--- a/src/java.base/aix/native/libnio/ch/AixPollPort.c
+++ b/src/java.base/aix/native/libnio/ch/AixPollPort.c
@@ -30,6 +30,7 @@
 #include "jlong.h"
 
 #include "sun_nio_ch_AixPollPort.h"
+#include "net_util_md.h"
 
 #include <unistd.h>
 #include <sys/types.h>
@@ -137,7 +138,7 @@
 JNIEXPORT void JNICALL
 Java_sun_nio_ch_AixPollPort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
     int sp[2];
-    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
+    if (NET_SocketPair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
         JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
     } else {
         jint res[2];
diff --git a/src/java.base/linux/native/libnet/linux_close.c b/src/java.base/linux/native/libnet/linux_close.c
--- a/src/java.base/linux/native/libnet/linux_close.c
+++ b/src/java.base/linux/native/libnet/linux_close.c
@@ -24,6 +24,7 @@
  */
 
 #include <assert.h>
+#include <dlfcn.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -395,7 +396,31 @@
     BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );  }
 
-int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
+static int acceptFcntlCloexec(int s, struct sockaddr *addr, socklen_t *addrlen) {
+    int cs;
+    cs = accept(s, addr, addrlen);
+    if (cs != -1) {
+        // Best effort - return value is intentionally ignored since the connected
+        // socket was successfully created.
+        fcntl(cs, F_SETFD, FD_CLOEXEC);
+    }
+    return cs;
+}
+
+JNIEXPORT int JNICALL
+NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
+    static int (*accept4functionpointer)(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) = NULL;
+    static int accept4initialized = 0;
+    int cs;
+
+    if (!accept4initialized) {
+        accept4functionpointer = dlsym(RTLD_DEFAULT, "accept4");
+        accept4initialized = 1;
+    }
+
+    if (accept4functionpointer != NULL) {
+        BLOCKING_IO_RETURN_INT( s, accept4functionpointer(s, addr, addrlen, SOCK_CLOEXEC) );
+    }
     BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );  }
 
diff --git a/src/java.base/unix/native/libnet/Inet4AddressImpl.c b/src/java.base/unix/native/libnet/Inet4AddressImpl.c
--- a/src/java.base/unix/native/libnet/Inet4AddressImpl.c
+++ b/src/java.base/unix/native/libnet/Inet4AddressImpl.c
@@ -264,7 +264,7 @@
     int connect_rv = -1;
 
     // open a TCP socket
-    fd = socket(AF_INET, SOCK_STREAM, 0);
+    fd = NET_Socket(AF_INET, SOCK_STREAM, 0);
     if (fd == -1) {
         // note: if you run out of fds, you may not be able to load
         // the exception class, and get a NoClassDefFoundError instead.
@@ -503,7 +503,7 @@
 
     // Let's try to create a RAW socket to send ICMP packets.
     // This usually requires "root" privileges, so it's likely to fail.
-    fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+    fd = NET_Socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
     if (fd == -1) {
         return tcp_ping4(env, &sa, netif, timeout, ttl);
     } else {
diff --git a/src/java.base/unix/native/libnet/Inet6AddressImpl.c b/src/java.base/unix/native/libnet/Inet6AddressImpl.c
--- a/src/java.base/unix/native/libnet/Inet6AddressImpl.c
+++ b/src/java.base/unix/native/libnet/Inet6AddressImpl.c
@@ -461,7 +461,7 @@
     int connect_rv = -1;
 
     // open a TCP socket
-    fd = socket(AF_INET6, SOCK_STREAM, 0);
+    fd = NET_Socket(AF_INET6, SOCK_STREAM, 0);
     if (fd == -1) {
         // note: if you run out of fds, you may not be able to load
         // the exception class, and get a NoClassDefFoundError instead.
@@ -711,7 +711,7 @@
 
     // Let's try to create a RAW socket to send ICMP packets.
     // This usually requires "root" privileges, so it's likely to fail.
-    fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+    fd = NET_Socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
     if (fd == -1) {
         return tcp_ping6(env, &sa, netif, timeout, ttl);
     } else {
diff --git a/src/java.base/unix/native/libnet/NetworkInterface.c b/src/java.base/unix/native/libnet/NetworkInterface.c
--- a/src/java.base/unix/native/libnet/NetworkInterface.c
+++ b/src/java.base/unix/native/libnet/NetworkInterface.c
@@ -1055,7 +1055,7 @@
 static int openSocket(JNIEnv *env, int proto) {
     int sock;
 
-    if ((sock = socket(proto, SOCK_DGRAM, 0)) < 0) {
+    if ((sock = NET_Socket(proto, SOCK_DGRAM, 0)) < 0) {
         // If EPROTONOSUPPORT is returned it means we don't have
         // support for this proto so don't throw an exception.
         if (errno != EPROTONOSUPPORT) { @@ -1078,9 +1078,9 @@  static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
     int sock;
 
-    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+    if ((sock = NET_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
         if (errno == EPROTONOSUPPORT) {
-            if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+            if ((sock = NET_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
                 JNU_ThrowByNameWithMessageAndLastError
                     (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
                 return -1;
@@ -1315,9 +1315,9 @@
 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
     int sock;
 
-    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+    if ((sock = NET_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
         if (errno == EPROTONOSUPPORT) {
-            if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+            if ((sock = NET_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
                 JNU_ThrowByNameWithMessageAndLastError
                     (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
                 return -1;
@@ -1590,9 +1590,9 @@
     int sock, alreadyV6 = 0;
     struct lifreq if2;
 
-    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+    if ((sock = NET_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
         if (errno == EPROTONOSUPPORT) {
-            if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+            if ((sock = NET_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
                 JNU_ThrowByNameWithMessageAndLastError
                     (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
                 return -1;
@@ -1616,7 +1616,7 @@
         strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
         if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
             close(sock);
-            if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+            if ((sock = NET_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
                 JNU_ThrowByNameWithMessageAndLastError
                     (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
                 return -1;
@@ -1941,9 +1941,9 @@
 static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
     int sock;
 
-    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+    if ((sock = NET_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
         if (errno == EPROTONOSUPPORT) {
-            if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+            if ((sock = NET_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
                 JNU_ThrowByNameWithMessageAndLastError
                     (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
                 return -1;
diff --git a/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c b/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c
--- a/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c
+++ b/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c
@@ -904,7 +904,7 @@
         return;
     }
 
-    if ((fd = socket(domain, SOCK_DGRAM, 0)) == -1) {
+    if ((fd = NET_Socket(domain, SOCK_DGRAM, 0)) == -1) {
         JNU_ThrowByNameWithMessageAndLastError
             (env, JNU_JAVANETPKG "SocketException", "Error creating socket");
         return;
diff --git a/src/java.base/unix/native/libnet/PlainSocketImpl.c b/src/java.base/unix/native/libnet/PlainSocketImpl.c
--- a/src/java.base/unix/native/libnet/PlainSocketImpl.c
+++ b/src/java.base/unix/native/libnet/PlainSocketImpl.c
@@ -77,7 +77,7 @@
     int sv[2];
 
 #ifdef AF_UNIX
-    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
+    if (NET_SocketPair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
         return -1;
     }
 #else
@@ -178,7 +178,7 @@
         return;
     }
 
-    if ((fd = socket(domain, type, 0)) == -1) {
+    if ((fd = NET_Socket(domain, type, 0)) == -1) {
         /* note: if you run out of fds, you may not be able to load
          * the exception class, and get a NoClassDefFoundError
          * instead.
diff --git a/src/java.base/unix/native/libnet/SdpSupport.c b/src/java.base/unix/native/libnet/SdpSupport.c
--- a/src/java.base/unix/native/libnet/SdpSupport.c
+++ b/src/java.base/unix/native/libnet/SdpSupport.c
@@ -57,7 +57,7 @@
 
 #if defined(__solaris__)
     int domain = ipv6_available() ? AF_INET6 : AF_INET;
-    s = socket(domain, SOCK_STREAM, PROTO_SDP);
+    s = NET_Socket(domain, SOCK_STREAM, PROTO_SDP);
 #elif defined(__linux__)
     /**
      * IPv6 not supported by SDP on Linux @@ -66,7 +66,7 @@
         JNU_ThrowIOException(env, "IPv6 not supported");
         return -1;
     }
-    s = socket(AF_INET_SDP, SOCK_STREAM, 0);
+    s = NET_Socket(AF_INET_SDP, SOCK_STREAM, 0);
 #else
     /* not supported on other platforms at this time */
     s = -1;
diff --git a/src/java.base/unix/native/libnet/net_util_md.c b/src/java.base/unix/native/libnet/net_util_md.c
--- a/src/java.base/unix/native/libnet/net_util_md.c
+++ b/src/java.base/unix/native/libnet/net_util_md.c
@@ -131,6 +131,52 @@
     return (result == -1) ? 0 : 1;
 }
 
+ /*
+  * Creates a socket.
+  * Uses SOCK_CLOEXEC during creation or FD_CLOEXEC post-creation, 
+ where possible
+  * and on a best-effort basis, on systems that support it.
+  */
+ JNIEXPORT int JNICALL
+ NET_Socket(int domain, int type, int protocol) {
+     int s;
+ #if defined(SOCK_CLOEXEC)
+     s = socket(domain, type | SOCK_CLOEXEC, protocol);
+     if (s != -1 || (s == -1 && errno != EINVAL)) {
+         return s;
+     }
+ #endif
+     s = socket(domain, type, protocol);
+     if (s != -1) {
+         // Best effort - return value is intentionally ignored since the socket
+         // was successfully created.
+         fcntl(s, F_SETFD, FD_CLOEXEC);
+     }
+     return s;
+ }
+
+/*
+ * Creates a pair of connected sockets.
+ * Uses SOCK_CLOEXEC during creation or FD_CLOEXEC post-creation, where 
+possible
+ * and on a best-effort basis, on systems that support it.
+ */
+JNIEXPORT int JNICALL
+NET_SocketPair(int domain, int type, int protocol, int socket_vector[2]) {
+    int s;
+#if defined(SOCK_CLOEXEC)
+    s = socketpair(domain, type | SOCK_CLOEXEC, protocol, socket_vector);
+    if (s != -1 || (s == -1 && errno != EINVAL)) {
+        return s;
+    }
+#endif
+    s = socketpair(domain, type, protocol, socket_vector);
+    if (s != -1) {
+        // Best effort - return value is intentionally ignored since the socket
+        // was successfully created.
+        fcntl(s, F_SETFD, FD_CLOEXEC);
+    }
+    return s;
+}
+
 #ifdef __solaris__
 static int init_tcp_max_buf, init_udp_max_buf;  static int tcp_max_buf; @@ -295,7 +341,7 @@
     SOCKETADDRESS sa;
     socklen_t sa_len = sizeof(SOCKETADDRESS);
 
-    fd = socket(AF_INET6, SOCK_STREAM, 0) ;
+    fd = NET_Socket(AF_INET6, SOCK_STREAM, 0) ;
     if (fd < 0) {
         /*
          *  TODO: We really cant tell since it may be an unrelated error @@ -402,7 +448,7 @@
     /* Do a simple dummy call, and try to figure out from that */
     int one = 1;
     int rv, s;
-    s = socket(PF_INET, SOCK_STREAM, 0);
+    s = NET_Socket(PF_INET, SOCK_STREAM, 0);
     if (s < 0) {
         return JNI_FALSE;
     }
diff --git a/src/java.base/unix/native/libnet/net_util_md.h b/src/java.base/unix/native/libnet/net_util_md.h
--- a/src/java.base/unix/native/libnet/net_util_md.h
+++ b/src/java.base/unix/native/libnet/net_util_md.h
@@ -77,6 +77,9 @@
  * Functions
  */
 
+JNIEXPORT int JNICALL NET_Socket(int domain, int type, int protocol); 
+JNIEXPORT int JNICALL NET_SocketPair(int domain, int type, int 
+protocol, int socket_vector[2]);
+
 int NET_Timeout(JNIEnv *env, int s, long timeout, jlong  nanoTimeStamp);  int NET_Read(int s, void* buf, size_t len);  int NET_NonBlockingRead(int s, void* buf, size_t len); @@ -88,7 +91,7 @@
                flags, const struct sockaddr *to, int tolen);  int NET_Writev(int s, const struct iovec * vector, int count);  int NET_Connect(int s, struct sockaddr *addr, int addrlen); -int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+JNIEXPORT int JNICALL NET_Accept(int s, struct sockaddr *addr, 
+socklen_t *addrlen);
 int NET_SocketClose(int s);
 int NET_Dup2(int oldfd, int newfd);
 int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout); diff --git a/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c b/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c
--- a/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c
+++ b/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c
@@ -56,6 +56,7 @@
 #include "jlong.h"
 #include "nio.h"
 #include "nio_util.h"
+#include "net_util_md.h"
 #include "sun_nio_ch_FileDispatcherImpl.h"
 #include "java_lang_Long.h"
 
@@ -67,7 +68,7 @@
 Java_sun_nio_ch_FileDispatcherImpl_init(JNIEnv *env, jclass cl)  {
     int sp[2];
-    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) {
+    if (NET_SocketPair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) {
         JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
         return;
     }
diff --git a/src/java.base/unix/native/libnio/ch/Net.c b/src/java.base/unix/native/libnio/ch/Net.c
--- a/src/java.base/unix/native/libnio/ch/Net.c
+++ b/src/java.base/unix/native/libnio/ch/Net.c
@@ -198,7 +198,7 @@
     int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
     int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;
 
-    fd = socket(domain, type, 0);
+    fd = NET_Socket(domain, type, 0);
     if (fd < 0) {
         return handleSocketError(env, errno);
     }
diff --git a/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c b/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c
--- a/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c
+++ b/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c
@@ -92,7 +92,7 @@
      * accept() was called.
      */
     for (;;) {
-        newfd = accept(ssfd, &sa.sa, &sa_len);
+        newfd = NET_Accept(ssfd, &sa.sa, &sa_len);
         if (newfd >= 0) {
             break;
         }
diff --git a/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c b/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c
--- a/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c
+++ b/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c
@@ -31,6 +31,7 @@
 #include <netinet/tcp.h>
 #include <netinet/in.h>
 #include "jni_util.h"
+#include "net_util_md.h"
 #include "jdk_net_LinuxSocketOptions.h"
 
 /*
@@ -86,7 +87,7 @@
 (JNIEnv *env, jobject unused) {
     int one = 1;
     int rv, s;
-    s = socket(PF_INET, SOCK_STREAM, 0);
+    s = NET_Socket(PF_INET, SOCK_STREAM, 0);
     if (s < 0) {
         return JNI_FALSE;
     }
@@ -103,7 +104,7 @@
 static jint socketOptionSupported(jint sockopt) {
     jint one = 1;
     jint rv, s;
-    s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+    s = NET_Socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
     if (s < 0) {
         return 0;
     }
diff --git a/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c b/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c
--- a/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c
+++ b/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c
@@ -31,11 +31,12 @@
 #include <netinet/tcp.h>
 #include <netinet/in.h>
 #include "jni_util.h"
+#include "net_util_md.h"
 
 static jint socketOptionSupported(jint sockopt) {
     jint one = 1;
     jint rv, s;
-    s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+    s = NET_Socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
     if (s < 0) {
         return 0;
     }
diff --git a/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c b/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c
--- a/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c
+++ b/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c
@@ -157,7 +157,7 @@
     sock_flow_props_t props;
     int rv, s;
 
-    s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+    s = NET_Socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
     if (s < 0) {
         return JNI_FALSE;
     }
diff --git a/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h b/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h
--- a/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h
+++ b/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h
@@ -36,6 +36,7 @@
 #include "jdk_net_SocketFlow.h"
 #include "SolarisSocketOptions.h"
 #include "jdk_net_SolarisSocketOptions.h"
+#include "net_util_md.h"
 
 #ifndef SO_FLOW_SLA
 #define SO_FLOW_SLA 0x1018
diff --git a/src/jdk.sctp/unix/native/libsctp/SctpNet.c b/src/jdk.sctp/unix/native/libsctp/SctpNet.c
--- a/src/jdk.sctp/unix/native/libsctp/SctpNet.c
+++ b/src/jdk.sctp/unix/native/libsctp/SctpNet.c
@@ -151,7 +151,7 @@
 Java_sun_nio_ch_sctp_SctpNet_init
   (JNIEnv *env, jclass cl) {
     int sp[2];
-    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) {
+    if (NET_SocketPair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) {
         JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
         return;
     }
@@ -180,7 +180,7 @@
         return 0;
     }
 
-    fd = socket(domain, (oneToOne ? SOCK_STREAM : SOCK_SEQPACKET), IPPROTO_SCTP);
+    fd = NET_Socket(domain, (oneToOne ? SOCK_STREAM : SOCK_SEQPACKET), 
+ IPPROTO_SCTP);
 
     if (fd < 0) {
         return handleSocketError(env, errno);

Thanks,

-Andrew

-----Original Message-----
From: net-dev <net-dev-bounces at openjdk.java.net> On Behalf Of Andrew Luo
Sent: Thursday, July 26, 2018 11:31 AM
To: Ivan Gerasimov <ivan.gerasimov at oracle.com>; Chris Hegarty <chris.hegarty at oracle.com>
Cc: net-dev at openjdk.java.net
Subject: RE: [PATCH] SOCK_CLOEXEC for opening sockets

Do we need to support compiling on a newer kernel with newer headers and then running the compiled binaries on an older platform?  If so, then I think we probably have to use dlsym to call accept4 at runtime rather than compile time...

Thanks,

-Andrew

-----Original Message-----
From: net-dev <net-dev-bounces at openjdk.java.net> On Behalf Of Ivan Gerasimov
Sent: Wednesday, July 25, 2018 10:04 PM
To: Chris Hegarty <chris.hegarty at oracle.com>
Cc: net-dev at openjdk.java.net
Subject: Re: [PATCH] SOCK_CLOEXEC for opening sockets

Hi Chris!

A couple of minor comments.

1)
if (s != -1 || (s == -1 && errno != EINVAL)) {

This can be simplified to

if (s != -1 || errno != EINVAL) {

2)
What about sockets created with accept():  Shouldn't NET_Accept be modified to set O_CLOEXEC as well?
On Linux accept4() can be used to pass SOCK_CLOEXEC flag.

With kind regards,
Ivan

On 7/25/18 5:49 AM, Chris Hegarty wrote:
> Alan,
>
>> On 25 Jul 2018, at 08:24, Alan Bateman <Alan.Bateman at oracle.com> wrote:
>>
>> ...
>>
>> As I said previously, the patch isn't complete so native code calling fork/exec may still have to deal with other file descriptors that are inherited into the child. I don't object to doing this in phases of course but somehow we have managed to get by for 20 years without this being an issue.
> I added the following to the JIRA description to make this clear:
>
> "This JIRA issue, by itself, does not completely resolve the problem 
> of native code calling fork/exec, it may still have to deal with other 
> file descriptors that are inherited by the child. Instead this JIRA 
> issue is targeted at the socket and channels areas only, other areas 
> should be tackled on a phased approach though separate JIRA issues."
>
>> The updates to the various site to use the NET_* functions are fine. However, I think the new functions in net_util_md.c could be cleaner. I think it would be better to fallback to socket/socketpair + fcntl when the initial call fails with EINVAL.
> Agreed. How about this ( trying to reduce the ifdef blocks, and keep 
> them relatively clean ) :
>
> ---
> JNIEXPORT int JNICALL
> NET_Socket(int domain, int type, int protocol) {
>      int s;
> #if defined(SOCK_CLOEXEC)
>      s = socket(domain, type | SOCK_CLOEXEC, protocol);
>      if (s != -1 || (s == -1 && errno != EINVAL)) {
>          return s;
>      }
> #endif
>      s = socket(domain, type, protocol);
>      if (s != -1) {
>          // Best effort - return value is intentionally ignored since the socket
>          // was successfully created.
>          fcntl(s, F_SETFD, FD_CLOEXEC);
>      }
>      return s;
> }
> ---
>
> Updated webrev:
>    http://cr.openjdk.java.net/~chegar/8207335/webrev.01/
>
> -Chris.

--
With kind regards,
Ivan Gerasimov



More information about the net-dev mailing list