diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index cda752ccf8d..71eafe1c3fb 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1243,6 +1243,30 @@ char* os::format_boot_path(const char* format_string, return formatted_path; } +// This function is a proxy to fopen, it tries to add a non standard flag ('e' or 'N') +// that ensures automatic closing of the file on exec. If it can not find support in +// the underlying c library, it will make an extra system call (fcntl) to ensure automatic +// closing of the file on exec. +FILE* os::fopen(const char* path, const char* mode) { + char modified_mode[20]; + assert(strlen(mode) + 1 < sizeof(modified_mode), "mode chars plus one extra must fit in buffer"); + sprintf(modified_mode, "%s" LINUX_ONLY("e") BSD_ONLY("e") WINDOWS_ONLY("N"), mode); + FILE* file = ::fopen(path, modified_mode); + +#if !(defined LINUX || defined BSD || defined _WINDOWS) + // assume fcntl FD_CLOEXEC support as a backup solution when 'e' or 'N' + // is not supported as mode in fopen + if (file != NULL) { + int fd = fileno(file); + if (fd != -1) { + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); + } + } +#endif + + return file; +} + bool os::set_boot_path(char fileSep, char pathSep) { const char* home = Arguments::get_java_home(); int home_len = (int)strlen(home);