8193072: File.delete() should remove its path from DeleteOnExitHook.files

Peter Levart peter.levart at gmail.com
Thu Jul 11 07:47:11 UTC 2019


On 7/11/19 3:51 AM, Ivan Gerasimov wrote:
> On 7/10/19 5:17 PM, Brian Burkhalter wrote:
>> I incorporated Peter’s version, adding the security check in 
>> cancelDeleteOnExit(), tweaking its verbiage along with that of 
>> deleteOnExit(), and modified the test DeleteOnExit to verify the new 
>> method. The updated version is here:
>> http://cr.openjdk.java.net/~bpb/8193072/webrev.03/ 
>> <http://cr.openjdk.java.net/~bpb/8193072/webrev.03/>
> There is possibility of a race here in a scenario like this:
> File dir = new File("dir");
> File file = new File("dir/file");
> -- thread 1 --
> dir.deleteOnExit();
> file.deleteOnExit();
> ///
> dir.cancelDeleteOnExit();
> ////  thread 2 intervenes
> file.cancelDeleteOnExit();
> -- end --
> -- thread 2 --
> dir.deleteOnExit();
> file.deleteOnExit();
> -- end --
> The result will be that the order of the registered files will change, 
> and JVM will try to delete dir first (this will fail as it is not empty).
> Of course it could be avoided, if cancellation were done in reverse 
> order, though it's not immediately obvious from the documentation.


LinkedHashMap.computeIfAbsent/computeIfPresent can also honor the so 
called "access order" which always moves the entry to the end of the 
linked list regardless of whether the entry is already present or not. 
So in above scenario and if LinkedHashMap was constructed with 
accessOrder=true, the registration order of paths after each operation 
would be as follows (the order of deletion is the reverse order of the 
presented registration order):

File dir = new File("dir");
File file = new File("dir/file");

-- thread 1 --


[dir, dir/file]


-- thread 2 --

[dir/file, dir]

[dir, dir/file]

-- thread 1 --

[dir, dir/file]

But that is just coincidence. There are other interleavings which would 
cause LHM "access order" to reorder paths in undesired way. Perhaps the 
best behavior would be for deleteOnExit() to reorder the file to the end 
of the registration list while cancelDeleteOnExit() to not change the 
order of registered paths. For example, like this:


This does however change the order of registration for sequences like 
the following:


Order of deletion now: file2, file1
Order of deletion with this patch: file1, file2

But considering that programs that register multiple files do so 
consistently (always the same set of related files in one go in the same 
order) or register unrelated files in unimportant order, such behavior 
is perhaps acceptable.

What do you think?

Regards, Peter

More information about the core-libs-dev mailing list