Thread interruption while reading from a ZipFS entry will close the entire FS

Bruno Ploumhans bruno.ploumhans at gmail.com
Fri Apr 12 17:42:02 UTC 2024


 Hi,

When reading from a zip file on the disk, ZipFileSystem uses a
SeekableByteChannel internally to read from the zip file. Unfortunately,
this channel is interruptible, and therefore a single thread interruption
while reading from a ZipPath will make the entire ZipFS unusable. This is
problematic for long-lived ZipFileSystems that can be used by multiple
threads. I suppose that this is a bug?

One workaround is to use deep reflection to call `setUninterruptible()` on
the underlying file channel if supported, however I am not sure of the
side-effects. It does seem to fix this issue though.

I couldn't get https://bugreport.java.com to work so I'm posting this here
instead. Thanks in advance.

Regards,
Bruno Ploumhans

PS: Here is a snippet that consistently reproduces the issue on my machine:
it crashes on the second read attempt with a `ClosedChannelException`.

import java.io.*;
import java.nio.file.*;
import java.util.zip.*;

public class nio_repro {
    public static void main(String[] args) throws Exception {
        // Create a dummy test.zip
        File f = new File("test.zip");
        try (ZipOutputStream out = new ZipOutputStream(new
FileOutputStream(f))) {
            ZipEntry e = new ZipEntry("entry1.txt");
            out.putNextEntry(e);

            byte[] data1 = "Text1".repeat(100000000).getBytes(); // Large
entry so it takes time to read
            out.write(data1, 0, data1.length);
            out.closeEntry();
        }

        // Open zip FS
        FileSystem fs = FileSystems.newFileSystem(f.toPath());
        // Start reading on second thread
        Thread secondThread = Thread.ofPlatform().start(() -> {
            try {
                byte[] contents =
Files.readAllBytes(fs.getPath("entry1.txt"));
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
        });
        Thread.sleep(1);
        // Interrupt read
        secondThread.interrupt();
        // Try to read again - this should crash with a
ClosedChannelException
        byte[] contents = Files.readAllBytes(fs.getPath("entry1.txt"));

        System.out.println("Successfully read " + contents.length + "
bytes.");
    }
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/nio-dev/attachments/20240412/ba32aa0b/attachment.htm>


More information about the nio-dev mailing list