jenkinsci/jenkins — pull request #615 by pjdarton (2012-11-12 16:51:26+00:00)
Title: Prospective fix for JENKINS-15331 (new and improved)

I've written (what I hope to be) a fix for https://issues.jenkins-ci.org/browse/JENKINS-15331. Unlike my previous post on this subject, this contains improved functionality (uses same tactics as Ant to delete files on Windows), and the file diffs are sensible.
This fix can either be pulled from here, or grabbed from the patch I've uploaded to JIRA.

Features:

Added three new system properties that control behavior (defaults should be acceptable to all, but configurable if necessary):
- "Util.deletionRetries" (an integer, defaults to 3),
- "Util.deletionRetryWait" (an integer, defaults to 100ms),
- "Util.performGCOnFailedDelete" (boolean, defaults to true on Windows, false everywhere else).
Delete operations that affect directories now try to delete the entire contents of the directory, continuing on to subfolders etc even after encountering files that wouldn't die, before eventually throwing an exception about what wouldn't die. i.e. if a folder has a file "a", "b" and "c", and you can't delete "b", then "a" and "c" would get deleted (and you'll still get the exception about "b").
Delete operations now have multiple attempts at deleting things (not just "twice"), so if not everything could be deleted first time around, maybe they'll get deleted 2nd/3rd etc time around. An exception is only thrown if all retry attempts are exhausted and there are still files/directories that won't delete.
On Windows, it defaults to calling System.gc() before retrying the delete. This approach is used by Apache Ant to workaround much the same problem, namely that deleting files on Windows isn't reliable (and the Ant devs seem to think that this is the right thing to do).

Disclaimers:

Whilst I've added unit-tests that prove that the deletion behavior is as I intended, I have yet to prove to that this actually fixes the issue. I am reasonably sure it makes it no worse ("it works for me") but, due to the unpredictable nature of the fault, it's difficult to prove a fix has fixed it, one can merely wait and see if it re-occurs.