Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#1931 closed defect (fixed)

Sorting error prevents I2P-Bote from deleting email packets

Reported by: lv-server Owned by: str4d
Priority: minor Milestone: 0.9.29
Component: apps/plugins Version: 0.9.23
Keywords: I2P-Bote Cc:
Parent Tickets: Sensitive: no

Description

[str4d: This was sent to me December 2015 via I2P-Bote, but I didn't get a ticket created for it at the time.]

There was a problem with my old address, I was able to send mails but I havent received anything. I was trying to send mails to self without success.

I2P version: 0.9.23-0
Java version: Oracle Corporation 1.8.0_66 (Java™ SE Runtime Environment 1.8.0_66-b18)
Wrapper version: 3.5.25
Server version: 8.1.17.v20150415
Servlet version: Jasper JSP 2.1 Engine
Platform: Windows 7 x86 6.1

15.4.12 14:32:43 ERROR [ExpiratnThrd] .bote.service.ExpirationThread: Exception caught in ExpirationThread loop
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(Unknown Source)
at java.util.TimSort.mergeAt(Unknown Source)
at java.util.TimSort.mergeForceCollapse(Unknown Source)
at java.util.TimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at i2p.bote.folder.Folder.getFilenames(Folder.java:98)
at i2p.bote.folder.DeletionAwareDhtFolder.getFilenames(DeletionAwareDhtFolder.java:127)
at i2p.bote.folder.Folder.iterate(Folder.java:125)
at i2p.bote.folder.PacketFolder$1.<init>(PacketFolder.java:97)
at i2p.bote.folder.PacketFolder.iterator(PacketFolder.java:96)
at i2p.bote.folder.EmailPacketFolder.deleteExpired(EmailPacketFolder.java:142)
at i2p.bote.service.ExpirationThread.run(ExpirationThread.java:53)

Subtickets

Change History (5)

comment:1 Changed 3 years ago by str4d

I'm guessing this was in I2P-Bote 0.4.1 or 0.4.2.

Similar to #811. The relevant code here is:

    protected File[] getFilenames() {
        File[] files = storageDir.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.toUpperCase().endsWith(fileExtension.toUpperCase());
            }
        });
        if (files == null) {
            log.error("Cannot list files in directory <" + storageDir + ">");
            files = new File[0];
        } else
            // sort files by date, newest first
            Arrays.sort(files, new Comparator<File>() {
                @Override
                public int compare(File f1, File f2) {
                    return (int)Math.signum(f2.lastModified() - f1.lastModified());
                }
            });

        return files;
    }

File.lastModified() should always return either the time of last modification, or 0. So what is likely the problem is that the packets in the folder were being updated at the same time as this was running, making File.lastModified() non-deterministic.

The ordering of packets is non-critical (ordering newest-first is AFAICT just an optimisation for generally needing the latest packets), so I will solve this in the same fashion as #811.

comment:2 Changed 3 years ago by str4d

Fixed in d6191ad2c056f0014f468023cfe115b1cd21baf4.

comment:3 Changed 3 years ago by zzz

Owner: set to str4d
Status: newassigned

This is a Java 8 thing, where the sort algo changed. Happened years ago over in router code, where it was exceedingly rare, and I just fixed it by catching IAE and retrying (or not, can't recall).

comment:4 Changed 3 years ago by str4d

Resolution: fixed
Status: assignedclosed

I'm not bothered with retrying, because the code calling this wants to iterate over the whole folder, so ordering doesn't matter.

comment:5 Changed 3 years ago by str4d

Milestone: undecided0.9.29
Note: See TracTickets for help on using tickets.