114 lines
3.7 KiB
Diff
114 lines
3.7 KiB
Diff
|
# HG changeset patch
|
||
|
# User martin
|
||
|
# Date 1494116427 -3600
|
||
|
# Sun May 07 01:20:27 2017 +0100
|
||
|
# Node ID 0bd3170be8c729dfaa88e7aa97449b2f36c650a9
|
||
|
# Parent baf64c88538f477d7f5a0cf90b670108ac312375
|
||
|
8043780, PR3368: 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
|
||
|
|
||
|
diff --git a/src/os/linux/vm/os_linux.cpp b/src/os/linux/vm/os_linux.cpp
|
||
|
--- openjdk/hotspot/src/os/linux/vm/os_linux.cpp
|
||
|
+++ openjdk/hotspot/src/os/linux/vm/os_linux.cpp
|
||
|
@@ -5282,38 +5282,16 @@
|
||
|
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
|
||
|
- * 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
|
||
|
- * appropriate file descriptors (e.g. as we do in closeDescriptors in
|
||
|
- * UNIXProcess.c), and this in turn might:
|
||
|
+
|
||
|
+ /* 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 appropriate file descriptors
|
||
|
+ * (e.g. as we do in closeDescriptors in UNIXProcess.c), and this in
|
||
|
+ * turn might:
|
||
|
*
|
||
|
* - cause end-of-file to fail to be detected on some file
|
||
|
* descriptors, resulting in mysterious hangs, or
|
||
|
@@ -5329,12 +5307,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) {
|