-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Centralize cleanup tasks and close created URLClassLoader instances
This ensures that library JAR files stored in the launcher and harness scratch directories are closed before removing the scratch directory roots. This was a problem on NFS, where the open files could not be unlinked from the directory (NFS kept around '.nfs*' temporaries), preventing the removal of the directories.
- Loading branch information
Showing
3 changed files
with
88 additions
and
16 deletions.
There are no files selected for viewing
80 changes: 80 additions & 0 deletions
80
renaissance-core/src/main/java/org/renaissance/core/Cleaner.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package org.renaissance.core; | ||
|
||
import java.io.Closeable; | ||
import java.io.IOException; | ||
import java.nio.file.Path; | ||
import java.util.LinkedHashSet; | ||
import java.util.Objects; | ||
import java.util.Set; | ||
|
||
final class Cleaner { | ||
private static Set<Closeable> registeredCloseables = new LinkedHashSet<>(); | ||
private static Set<Path> registeredPaths = new LinkedHashSet<>(); | ||
|
||
private Cleaner() { | ||
// Not to be instantiated. | ||
} | ||
|
||
static synchronized Path deleteOnExit(Path path) { | ||
if (registeredPaths == null) { | ||
throw new IllegalStateException("Shutdown in progress"); | ||
} else { | ||
registeredPaths.add(Objects.requireNonNull(path)); | ||
} | ||
|
||
return path; | ||
} | ||
|
||
static synchronized <T extends Closeable> T closeOnExit(T closeable) { | ||
if (registeredCloseables == null) { | ||
throw new IllegalStateException("Shutdown in progress"); | ||
} else { | ||
registeredCloseables.add(Objects.requireNonNull(closeable)); | ||
} | ||
|
||
return closeable; | ||
} | ||
|
||
private static void run() { | ||
Set<Path> paths; | ||
Set<Closeable> closeables; | ||
|
||
synchronized (Cleaner.class) { | ||
closeables = registeredCloseables; | ||
registeredCloseables = null; | ||
|
||
paths = registeredPaths; | ||
registeredPaths = null; | ||
} | ||
|
||
// Close closeables BEFORE deleting files/directories. | ||
// In particular URLClassLoader instances which keep files open. | ||
|
||
closeables.forEach(closeable -> { | ||
try { | ||
closeable.close(); | ||
} catch (IOException e) { | ||
// Just a notification. This should be rare and is not critical. | ||
System.err.format("warning: failed to close %s on shutdown: %s\n", closeable, e); | ||
} | ||
}); | ||
|
||
closeables.clear(); | ||
|
||
// Delete files/directories AFTER closing closeables. | ||
|
||
paths.forEach(path -> { | ||
try { | ||
DirUtils.deleteRecursively(path); | ||
} catch (IOException e) { | ||
// Just a notification. This should be rare (not so much on NFS) and is not critical. | ||
System.err.format("warning: failed to delete %s on shutdown: %s\n", path, e); | ||
} | ||
}); | ||
} | ||
|
||
static { | ||
Runtime.getRuntime().addShutdownHook(new Thread(Cleaner::run)); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters