fopen vs. os::fopen and automatic closing of the file on exec

Thomas Stüfe thomas.stuefe at gmail.com
Tue Jan 28 18:10:44 UTC 2020


Hi Leo,

On Tue, Jan 28, 2020 at 4:37 PM Leo Korinth <leo.korinth at oracle.com> wrote:
...


> Something that is not obvious is that on unix-like operating systems,
> ProcessImpl_md.c tries to close (most) open files between fork and exec.
> That is not the case for Windows (I opened
> https://bugs.openjdk.java.net/browse/JDK-8202720 for this). Thus (if I
> understand correctly) the impact on unix-like operating systems will be
> less for adding this support than it is for Windows. os::fopen was
> created to solve a specific bug on windows (logging), and was renamed to
> the more generic os::fopen during review.
>
>
Just a note, it is still possible for file descriptors to escape into child
processes since you cannot guarantee that all forks happen via
Runtime.exec():
- native third party code may fork.
- hotspot may fork to run tools for error reporting

Also note that the code which closes fds in Runtime.exec() may in theory
fail to close all fds.

So I think Matthias makes sense on Posix platforms.


> I guess most uses of ::fopen /should/ use the more restricted os::fopen,
> but the gain would probably be small.
>
> Thanks,
> Leo
> > David
> >
> >> Best regards, Matthias
> >>
> >>
> >>
> >> Grep showed  me these fopen-calls in HS, a lot go not to os::fopen ?
> >>
> >> cpu/aarch64/vm_version_aarch64.cpp:171:  if (FILE *f =
> >> fopen("/proc/cpuinfo", "r")) {
> >> cpu/ppc/vm_version_ppc.cpp:412:  FILE* fp = fopen(info_file, "r");
> >> os/aix/os_aix.cpp:3756:  // - might cause an fopen in the subprocess
> >> to fail on a system
> >> os/aix/os_perf_aix.cpp:243:  if ((f = fopen(procfile, "r")) == NULL) {
> >> os/aix/os_perf_aix.cpp:666:  if ((fp = fopen(buffer, "r")) != NULL) {
> >> os/aix/os_perf_aix.cpp:694:  if ((fp = fopen(buffer, "r")) != NULL) {
> >> os/bsd/os_bsd.cpp:3479:  // - might cause an fopen in the subprocess
> >> to fail on a system
> >> os/linux/decoder_linux.cpp:61:  FILE* file = fopen(filepath, "r");
> >> os/linux/os_linux.cpp:257:  if ((fh = fopen("/proc/stat", "r")) ==
> >> NULL) {
> >> os/linux/os_linux.cpp:364:    FILE *fp = fopen(fname, "r");
> >> os/linux/os_linux.cpp:1106:  FILE *fp = fopen("/proc/self/maps", "r");
> >> os/linux/os_linux.cpp:1218:    fp = fopen("/proc/self/stat", "r");
> >> os/linux/os_linux.cpp:2075:  if ((procmapsFile =
> >> fopen("/proc/self/maps", "r")) != NULL) {
> >> os/linux/os_linux.cpp:2244:  FILE* fp = fopen(file, "r");
> >> os/linux/os_linux.cpp:2458:  FILE *fp = fopen("/proc/cpuinfo", "r");
> >> os/linux/os_linux.cpp:2515:  FILE* fp = fopen("/proc/cpuinfo", "r");
> >> os/linux/os_linux.cpp:3645:    FILE *fp = fopen("/proc/self/maps", "r");
> >> os/linux/os_linux.cpp:3689:  if ((f =
> >> fopen("/proc/self/coredump_filter", "r+")) == NULL) {
> >> os/linux/os_linux.cpp:3741:  FILE *fp = fopen("/proc/meminfo", "r");
> >> os/linux/os_linux.cpp:5572:  // - might cause an fopen in the
> >> subprocess to fail on a system
> >> os/linux/os_linux.cpp:5797:  fp = fopen(proc_name, "r");
> >> os/linux/os_perf_linux.cpp:238:  if ((f = fopen(procfile, "r")) ==
> >> NULL) {
> >> os/linux/os_perf_linux.cpp:275:  if ((f = fopen("/proc/stat", "r")) ==
> >> NULL) {
> >> os/linux/os_perf_linux.cpp:726:  if ((fp = fopen(buffer, "r")) != NULL)
> {
> >> os/linux/os_perf_linux.cpp:754:  if ((fp = fopen(buffer, "r")) != NULL)
> {
> >> os/linux/perfMemory_linux.cpp:659:  FILE *fp = fopen(fname, "r");
> >> os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp:312:  FILE* const file
> >> = fopen(filename, "r");
> >> os/linux/gc/z/zMountPoint_linux.cpp:72:  FILE* fd =
> >> fopen(PROC_SELF_MOUNTINFO, "r");
> >> os/linux/cgroupSubsystem_linux.cpp:66:  cgroups =
> >> fopen("/proc/cgroups", "r");
> >> os/linux/cgroupSubsystem_linux.cpp:121:  cgroup =
> >> fopen("/proc/self/cgroup", "r");
> >> os/linux/cgroupSubsystem_linux.cpp:170:    mntinfo =
> >> fopen("/proc/self/mountinfo", "r");
> >> os/linux/cgroupSubsystem_linux.cpp:224:  mntinfo =
> >> fopen("/proc/self/mountinfo", "r");
> >> os/linux/cgroupSubsystem_linux.hpp:96:  fp = fopen(file, "r");
> >> os/solaris/os_perf_solaris.cpp:521:      if ((fp = fopen(buffer, "r"))
> >> != NULL) {
> >> os/solaris/os_perf_solaris.cpp:557:  if ((fp = fopen(psinfo_path,
> >> "r")) == NULL) {
> >> os/solaris/os_solaris.cpp:1605:  FILE* fp = fopen("/etc/release", "r");
> >> os/solaris/os_solaris.cpp:4091:  //   fopen must be less than 256,
> >> _even_ when the first limit above
> >> os/solaris/os_solaris.cpp:4092:  //   has been raised.  This can cause
> >> calls to fopen (but not calls to
> >> os/solaris/os_solaris.cpp:4094:  //   native code (although the JDK
> >> itself uses fopen).  One can hardly
> >> os/solaris/os_solaris.cpp:4103:  //   stdio fopen limit by calling
> >> function enable_extended_FILE_stdio.
> >> os/solaris/os_solaris.cpp:4138:  // - might cause an fopen in the
> >> subprocess to fail on a system
> >> os_cpu/linux_sparc/vm_version_linux_sparc.cpp:39:    FILE* fp =
> >> fopen("/proc/cpuinfo", "r");
> >> share/logging/logFileOutput.cpp:272:  _stream = os::fopen(_file_name,
> >> FileOpenMode);
> >> share/logging/logFileOutput.cpp:361:  _stream = os::fopen(_file_name,
> >> FileOpenMode);
> >> share/runtime/arguments.cpp:1345:  FILE* stream = fopen(file_name,
> "rb");
> >> share/runtime/memprofiler.cpp:76:    _log_fp = fopen(log_name , "w+");
> >> share/runtime/os.cpp:1253:// This function is a proxy to fopen, it
> >> tries to add a non standard flag ('e' or 'N')
> >> share/runtime/os.cpp:1257:FILE* os::fopen(const char* path, const
> >> char* mode) {
> >> share/runtime/os.cpp:1261:  FILE* file = ::fopen(path, modified_mode);
> >> share/runtime/os.cpp:1265:  // is not supported as mode in fopen
> >> share/runtime/os.hpp:510:  static FILE* fopen(const char* path, const
> >> char* mode);
> >> share/runtime/abstract_vm_version.cpp:308:  FILE* fp = fopen(filename,
> >> "r");
> >> share/utilities/elfFile.cpp:171:  _file = fopen(filepath, "r");
> >> share/utilities/ostream.cpp:513:  _file = fopen(file_name, "w");
> >> share/utilities/ostream.cpp:523:  _file = fopen(file_name, opentype);
> >> share/adlc/main.cpp:363:      (ADF._fp = fopen(ADF._name, action)) ==
> >> NULL) {
> >> share/c1/c1_Compilation.cpp:697:  fileStream
> >> stream(fopen("c1_compile_only", "wt"));
> >> share/c1/c1_Compilation.cpp:713:  fileStream
> >> stream(fopen(".hotspot_compiler", "at"));
> >> share/ci/ciReplay.cpp:127:    _stream = fopen(filename, "rt");
> >> share/classfile/classListParser.cpp:51:  // Use os::open() because
> >> neither fopen() nor os::fopen()
> >> share/compiler/compileBroker.cpp:1891:      fp = fopen(file_name, "wt");
> >> share/compiler/compilerOracle.cpp:703:  FILE* stream =
> >> fopen(cc_file(), "rt");
> >> share/compiler/disassembler.cpp:272:        if ((fp = fopen(file,
> >> "r")) == NULL) {
> >>
>


More information about the hotspot-dev mailing list