org.eclipse.jgit.errors;version="[6.8.0,6.9.0)",
org.eclipse.jgit.internal.storage.file;version="[6.8.0,6.9.0)",
org.eclipse.jgit.internal.storage.pack;version="[6.8.0,6.9.0)",
+ org.eclipse.jgit.internal.util;version="[6.8.0,6.9.0)",
org.eclipse.jgit.lib;version="[6.8.0,6.9.0)",
org.eclipse.jgit.merge;version="[6.8.0,6.9.0)",
org.eclipse.jgit.revwalk;version="[6.8.0,6.9.0)",
import java.io.IOException;
import java.io.PrintStream;
import java.time.Instant;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.internal.storage.file.FileRepository;
+import org.eclipse.jgit.internal.util.ShutdownHook;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
@Before
public void setUp() throws Exception {
tmp = File.createTempFile("jgit_" + getTestName() + '_', "_tmp");
- CleanupThread.deleteOnShutdown(tmp);
+ Cleanup.deleteOnShutdown(tmp);
if (!tmp.delete() || !tmp.mkdir()) {
throw new IOException("Cannot create " + tmp);
}
recursiveDelete(tmp, false, true);
}
if (tmp != null && !tmp.exists()) {
- CleanupThread.removed(tmp);
+ Cleanup.removed(tmp);
}
SystemReader.setInstance(null);
}
return new HashMap<>(System.getenv());
}
- private static final class CleanupThread extends Thread {
- private static final CleanupThread me;
+ private static final class Cleanup {
+ private static final Cleanup INSTANCE = new Cleanup();
+
static {
- me = new CleanupThread();
- Runtime.getRuntime().addShutdownHook(me);
+ ShutdownHook.INSTANCE.register(() -> INSTANCE.onShutdown());
+ }
+
+ private final Set<File> toDelete = ConcurrentHashMap.newKeySet();
+
+ private Cleanup() {
+ // empty
}
static void deleteOnShutdown(File tmp) {
- synchronized (me) {
- me.toDelete.add(tmp);
- }
+ INSTANCE.toDelete.add(tmp);
}
static void removed(File tmp) {
- synchronized (me) {
- me.toDelete.remove(tmp);
- }
+ INSTANCE.toDelete.remove(tmp);
}
- private final List<File> toDelete = new ArrayList<>();
-
- @Override
- public void run() {
+ private void onShutdown() {
// On windows accidentally open files or memory
// mapped regions may prevent files from being deleted.
// Suggesting a GC increases the likelihood that our
x-friends:="org.eclipse.jgit.ssh.apache,
org.eclipse.jgit.ssh.jsch,
org.eclipse.jgit.test",
- org.eclipse.jgit.internal.util;version="6.8.0";x-internal:=true,
+ org.eclipse.jgit.internal.util;version="6.8.0";
+ x-friends:=" org.eclipse.jgit.junit",
org.eclipse.jgit.lib;version="6.8.0";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.util.sha1,
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.internal.util.ShutdownHook;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.BranchConfig.BranchRebaseMode;
import org.eclipse.jgit.lib.ConfigConstants;
private List<String> shallowExcludes = new ArrayList<>();
+ private ShutdownHook.Listener shutdownListener = this::cleanup;
+
private enum FETCH_TYPE {
MULTIPLE_BRANCHES, ALL_BRANCHES, MIRROR
}
@SuppressWarnings("resource") // Closed by caller
Repository repository = init();
FetchResult fetchResult = null;
- Thread cleanupHook = new Thread(() -> cleanup());
- try {
- Runtime.getRuntime().addShutdownHook(cleanupHook);
- } catch (IllegalStateException e) {
- // ignore - the VM is already shutting down
- }
+ ShutdownHook.INSTANCE.register(shutdownListener);
try {
fetchResult = fetch(repository, u);
} catch (IOException ioe) {
cleanup();
throw e;
} finally {
- try {
- Runtime.getRuntime().removeShutdownHook(cleanupHook);
- } catch (IllegalStateException e) {
- // ignore - the VM is already shutting down
- }
+ ShutdownHook.INSTANCE.unregister(shutdownListener);
}
try {
checkout(repository, fetchResult);
import org.eclipse.jgit.internal.storage.commitgraph.GraphCommits;
import org.eclipse.jgit.internal.storage.pack.PackExt;
import org.eclipse.jgit.internal.storage.pack.PackWriter;
+import org.eclipse.jgit.internal.util.ShutdownHook;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.CoreConfig;
private FileChannel channel;
- private Thread cleanupHook;
+ private ShutdownHook.Listener shutdownListener = this::close;
PidLock() {
pidFile = repo.getDirectory().toPath().resolve(GC_PID);
}
channel.write(ByteBuffer
.wrap(getProcDesc().getBytes(StandardCharsets.UTF_8)));
- try {
- Runtime.getRuntime().addShutdownHook(
- cleanupHook = new Thread(() -> close()));
- } catch (IllegalStateException e) {
- // ignore - the VM is already shutting down
- }
+ ShutdownHook.INSTANCE.register(shutdownListener);
} catch (IOException | OverlappingFileLockException e) {
try {
failedToLock();
public void close() {
boolean wasLocked = false;
try {
- if (cleanupHook != null) {
- try {
- Runtime.getRuntime().removeShutdownHook(cleanupHook);
- } catch (IllegalStateException e) {
- // ignore - the VM is already shutting down
- }
- }
+ ShutdownHook.INSTANCE.unregister(shutdownListener);
if (lock != null && lock.isValid()) {
lock.release();
wasLocked = true;
import org.eclipse.jgit.errors.LockFailedException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.storage.file.FileSnapshot;
+import org.eclipse.jgit.internal.util.ShutdownHook;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
static {
// Shut down the SAVE_RUNNER on System.exit()
+ ShutdownHook.INSTANCE
+ .register(FileStoreAttributes::shutdownSafeRunner);
+ }
+
+ private static void shutdownSafeRunner() {
try {
- Runtime.getRuntime().addShutdownHook(new Thread(() -> {
- try {
- SAVE_RUNNER.shutdownNow();
- SAVE_RUNNER.awaitTermination(100,
- TimeUnit.MILLISECONDS);
- } catch (Exception e) {
- // Ignore; we're shutting down
- }
- }));
- } catch (IllegalStateException e) {
- // ignore - may fail if shutdown is already in progress
+ SAVE_RUNNER.shutdownNow();
+ SAVE_RUNNER.awaitTermination(100, TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ // Ignore; we're shutting down
}
}