changeset 6526:8d8fc0174498 icedtea-2.7.0pre11

8043780, PR3369: Use open(O_CLOEXEC) instead of fcntl(FD_CLOEXEC) Summary: Use open(O_CLOEXEC) where available; fall back to FD_CLOEXEC when necessary Reviewed-by: rasbold, dholmes
author martin
date Wed, 26 Apr 2017 04:56:01 +0100
parents 83e23c65e336
children 07f42d8fd151
files src/os/linux/vm/os_linux.cpp
diffstat 1 files changed, 42 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/os/linux/vm/os_linux.cpp	Tue Mar 28 06:12:49 2017 -0400
+++ b/src/os/linux/vm/os_linux.cpp	Wed Apr 26 04:56:01 2017 +0100
@@ -5331,33 +5331,11 @@
     errno = ENAMETOOLONG;
     return -1;
   }
-  int fd;
   int o_delete = (oflag & O_DELETE);
   oflag = oflag & ~O_DELETE;
 
-  fd = ::open64(path, oflag, mode);
-  if (fd == -1) return -1;
-
-  //If the open succeeded, the file might still be a directory
-  {
-    struct stat64 buf64;
-    int ret = ::fstat64(fd, &buf64);
-    int st_mode = buf64.st_mode;
-
-    if (ret != -1) {
-      if ((st_mode & S_IFMT) == S_IFDIR) {
-        errno = EISDIR;
-        ::close(fd);
-        return -1;
-      }
-    } else {
-      ::close(fd);
-      return -1;
-    }
-  }
-
     /*
-     * All file descriptors that are opened in the JVM and not
+     * All file descriptors that are opened in the Java process and not
      * specifically destined for a subprocess should have the
      * close-on-exec flag set.  If we don't set it, then careless 3rd
      * party native code might fork and exec without closing all
@@ -5378,12 +5356,49 @@
      * 4843136: (process) pipe file descriptor from Runtime.exec not being closed
      * 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9
      */
+  // Modern Linux kernels (after 2.6.23 2007) support O_CLOEXEC with open().
+  // O_CLOEXEC is preferable to using FD_CLOEXEC on an open file descriptor
+  // because it saves a system call and removes a small window where the flag
+  // is unset.  On ancient Linux kernels the O_CLOEXEC flag will be ignored
+  // and we fall back to using FD_CLOEXEC (see below).
+#ifdef O_CLOEXEC
+  oflag |= O_CLOEXEC;
+#endif
+
+  int fd = ::open64(path, oflag, mode);
+  if (fd == -1) return -1;
+
+  //If the open succeeded, the file might still be a directory
+  {
+    struct stat64 buf64;
+    int ret = ::fstat64(fd, &buf64);
+    int st_mode = buf64.st_mode;
+
+    if (ret != -1) {
+      if ((st_mode & S_IFMT) == S_IFDIR) {
+        errno = EISDIR;
+        ::close(fd);
+        return -1;
+      }
+    } else {
+      ::close(fd);
+      return -1;
+    }
+  }
+
 #ifdef FD_CLOEXEC
-    {
-        int flags = ::fcntl(fd, F_GETFD);
-        if (flags != -1)
-            ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+  // Validate that the use of the O_CLOEXEC flag on open above worked.
+  // With recent kernels, we will perform this check exactly once.
+  static sig_atomic_t O_CLOEXEC_is_known_to_work = 0;
+  if (!O_CLOEXEC_is_known_to_work) {
+    int flags = ::fcntl(fd, F_GETFD);
+    if (flags != -1) {
+      if ((flags & FD_CLOEXEC) != 0)
+        O_CLOEXEC_is_known_to_work = 1;
+      else
+        ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
     }
+  }
 #endif
 
   if (o_delete != 0) {