fopen vs. os::fopen and automatic closing of the file on exec
David Holmes
david.holmes at oracle.com
Tue Jan 28 23:27:03 UTC 2020
Hi Matthias,
On 28/01/2020 11:44 pm, Baesken, Matthias wrote:
> Hi David, thanks for looking into it .
>
> While checking other open(64) calls, I found the fileOpen / handleOpen calls in java.base .
> Looks like they miss so far setting FD_CLOEXEC / O_CLOEXEC , it isn’t done in the callers of those functions and it is also not (silently) added in the fileOpen/handleOpen function itself (like HS does in os::open ).
> See :
>
> 73FD
> 74handleOpen(const char *path, int oflag, int mode) {
> 75 FD fd;
> 76 RESTARTABLE(open64(path, oflag, mode), fd);
> 77 if (fd != -1) {
> 78 struct stat64 buf64;
> 79 int result;
> 80 RESTARTABLE(fstat64(fd, &buf64), result);
> 81 if (result != -1) {
> 82 if (S_ISDIR(buf64.st_mode)) {
> 83 close(fd);
> 84 errno = EISDIR;
> 85 fd = -1;
> 86 }
> 87 } else {
> 88 close(fd);
> 89 fd = -1;
> 90 }
> 91 }
> 92 return fd;
> 93}
>
> 95void
> 96fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags)
> 97{
> .....
> 107 fd = handleOpen(ps, flags, 0666);
> ....
> 122}
>
> 56JNIEXPORT void JNICALL
> 57Java_java_io_FileOutputStream_open0(JNIEnv *env, jobject this,
> 58 jstring path, jboolean append) {
> 59 fileOpen(env, this, path, fos_fd,
> 60 O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC));
> 61}
>
> 59JNIEXPORT void JNICALL
> 60Java_java_io_FileInputStream_open0(JNIEnv *env, jobject this, jstring path) {
> 61 fileOpen(env, this, path, fis_fd, O_RDONLY);
> 62}
>
>
> Is this something that should be changed too ?
I think not. Unless those public API's are specified to open a file in a
specific mode, like close-on-exec, then they should not do that by default.
We should only be doing close-on-exec on internally used files.
David
-----
> Best regards, Matthias
>
>
>>
>> Hi Matthias,
>>
>> I don't have any info of most below but one follow up ....
>>
>> On 28/01/2020 10:51 pm, Baesken, Matthias wrote:
>>> Hello, I noticed while looking at
>> https://bugs.openjdk.java.net/browse/JDK-8237830 ( support O_CLOEXEC
>> in os::open on other OS than Linux )
>>> that os::fopen also has some support for setting FD_CLOEXEC /
>> O_CLOEXEC on the file opened .
>>> See :
>>>
>>> 1253// This function is a proxy to fopen, it tries to add a non standard flag
>> ('e' or 'N')
>>> 1254// that ensures automatic closing of the file on exec. If it can not find
>> support in
>>> 1255// the underlying c library, it will make an extra system call (fcntl) to
>> ensure automatic
>>> 1256// closing of the file on exec.
>>> 1257FILE* os::fopen(const char* path, const char* mode) {
>>> 1258 char modified_mode[20];
>>> 1259 assert(strlen(mode) + 1 < sizeof(modified_mode), "mode chars plus
>> one extra must fit in buffer");
>>> 1260 sprintf(modified_mode, "%s" LINUX_ONLY("e") BSD_ONLY("e")
>> WINDOWS_ONLY("N"), mode);
>>> 1261 FILE* file = ::fopen(path, modified_mode);
>>> 1262
>>> 1263#if !(defined LINUX || defined BSD || defined _WINDOWS)
>>> 1264 // assume fcntl FD_CLOEXEC support as a backup solution when 'e' or
>> 'N'
>>> 1265 // is not supported as mode in fopen
>>> 1266 if (file != NULL) {
>>> 1267 int fd = fileno(file);
>>> 1268 if (fd != -1) {
>>> 1269 int fd_flags = fcntl(fd, F_GETFD);
>>> 1270 if (fd_flags != -1) {
>>> 1271 fcntl(fd, F_SETFD, fd_flags | FD_CLOEXEC);
>>> 1272 }
>>> 1273 }
>>> 1274 }
>>> 1275#endif
>>>
>>> However some questions arise here :
>>>
>>> 1. Usage : os::fopen is only used sometimes in HS code , should
>> most of the calls to fopen be adjusted to os::fopen (see list below )
>>> 2. ::fopen vs. ::fcntl : is os_linux os::open we try to set the "closing
>> of the file on exec" flag when calling ::open but we later check that it really
>> worked so we seem not to trust it fully ;
>>
>> The check is for running on older Linuxes that do not support O_CLOEXEC
>> - where the flag is ignored. That is why I asked about what happens on
>> BSD/macOS and AIX in that situation.
>>
>>> Should this be done here too for Linux ? Or is that checking in os_linux
>> os::open these days not needed any more ?
>>
>> It's possible the most recent version of Linux without O_CLOEXEC
>> supported is no longer supported by OpenJDK, in which case we can remove
>> it. But I'm not sure what that version is. I have no idea if fopen with
>> "e" support has the same history as ::open and O_CLOEXEC.
>>
>> David
>>
>
More information about the hotspot-dev
mailing list