Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8037394

ZipFileSystem leaks file descriptor when file is not a valid zip file

XMLWordPrintable

    • b48
    • x86_64
    • linux_ubuntu

        FULL PRODUCT VERSION :
        java version "1.7.0_51"
        OpenJDK Runtime Environment (IcedTea 2.4.4) (7u51-2.4.4-0ubuntu0.13.10.1)
        OpenJDK 64-Bit Server VM (build 24.45-b08, mixed mode)


        ADDITIONAL OS VERSION INFORMATION :
        Linux mhassert 3.11.0-17-generic #31-Ubuntu SMP Mon Feb 3 21:52:43 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

        EXTRA RELEVANT SYSTEM CONFIGURATION :
        zipfs.jar containing package "com/sun/nio/zipfs" must be in classpath.
        Using Ubuntu, this is provided by the package "openjdk-7-jre-headless"

        A DESCRIPTION OF THE PROBLEM :
        Summary:
        When com.sun.nio.zipfs.ZipFileSystemProvider is present, all calls to java.nio.file.FileSystems.newFileSystem() for non-zip files leak an open file descriptor.

        Details:
        - When one calls java.nio.file.FileSystems.newFileSystem() for an existing file, all installed FileSystemProviders are checked by calling .newFileSystem() on them.
        - com.sun.nio.zipfs.ZipFileSystemProvider.newFileSystem() checks whether ZipFileSystem is applicable by trying to create a new Instance of it.
        - The constructor ZipFileSystem() opens in its second last line a new Channel to the file:
        this.ch = Files.newByteChannel(zfpath, READ);
        - In its last line it tries to access the zip content, aborting with an exception if not successfull:
        this.cen = initCEN();
        - In case of an exception the channel "this.ch" is never closed.

        Solution:
        I propose wrapping the last line in a try-catch-rethrow block, closing the channel in case of an exception.

        Note on bug priority:
        I am aware that ZipFileSystem is merely a demo and not an integral part of jre. But ironically this bug does not affect users of ZipFileSystem. It is a show-stopper for everyone using java.nio.file.FileSystems.newFileSystem() for any other kind of custom file system. It is enough to have ZipFileSystem on your system.

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Steps to reproduce:
        - Call java.nio.file.FileSystems.newFileSystem() for an existing file that is not a valid zip file. (An empty file will do)
        - ProviderNotFoundException is thrown as expected.
        - A file descriptor to the file is kept alive. (using Linux, check with lsof | grep PID)
        - By repeating this steps you will eventually hit the file descriptor limit of your OS and a FileSystemException is thrown.

        See also provided test case.


        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        I expect to safely call java.nio.file.FileSystems.newFileSystem() for non-zip files without side effects.
        All file descriptors opened by ZipFileSystem and ZipFileSystemProvider should be released when the file is not a zip file.
        ACTUAL -
        - A file descriptor to the file is kept alive. (using Linux, check with lsof | grep PID)


        ERROR MESSAGES/STACK TRACES THAT OCCUR :
        Exception in thread "main" java.nio.file.FileSystemException: /tmp/test: Too many open files
        at sun.nio.fs.UnixException.translateToIOException(UnixException.java:91)
        at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
        at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
        at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:214)
        at java.nio.file.Files.newByteChannel(Files.java:315)
        at java.nio.file.Files.newByteChannel(Files.java:361)
        at com.sun.nio.zipfs.ZipFileSystem.<init>(ZipFileSystem.java:129)
        at com.sun.nio.zipfs.ZipFileSystemProvider.newFileSystem(ZipFileSystemProvider.java:139)
        at java.nio.file.FileSystems.newFileSystem(FileSystems.java:386)
        at de.abm.dependencies.ZipFileSystemBug.main(ZipFileSystemBug.java:30)


        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        // file ZipFileSystemBug.java

        import java.nio.file.FileSystem;
        import java.nio.file.FileSystemException;
        import java.nio.file.FileSystems;
        import java.nio.file.Path;
        import java.nio.file.Paths;
        import java.nio.file.ProviderNotFoundException;

        /**
         * @author mhassert
         *
         */
        public class ZipFileSystemBug {
            
            private static final String EXISTING_NON_ZIP_FILE = "/tmp/test";
            
            /**
             * @param args
             * @throws Exception
             */
            public static void main(String[] args) throws Exception {
                
                Path path = Paths.get(EXISTING_NON_ZIP_FILE);
                int i = 0;
                while (true) {
                    try (FileSystem fs = FileSystems.newFileSystem(path, null);) {
                        throw new Exception("THIS SHOULD NEVER HAPPEN");
                    } catch (final ProviderNotFoundException e) {
                        // EXPECTED
                        System.out.println(i++);
                    } catch (FileSystemException e) {
                        // NOT EXPECTED!
                        e.printStackTrace();
                        throw e;
                    }
                }
            }
        }

        ---------- END SOURCE ----------

              sherman Xueming Shen
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated:
                Resolved: