Merge branch 'master' into stable-6.5

* master:
  If tryLock fails to get the lock another gc has it
  Fix GcConcurrentTest#testInterruptGc
  Don't swallow IOException in GC.PidLock#lock
  Check if FileLock is valid before using or releasing it

Change-Id: I0a599ec9241dd3b9b9a61122b2eda6bd647bcc22
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java
index 2c5f1a8..5f52e6b 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java
@@ -14,10 +14,10 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.io.IOException;
+import java.nio.channels.ClosedByInterruptException;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.concurrent.BrokenBarrierException;
@@ -226,10 +226,8 @@ public void testInterruptGc() throws Exception {
 			if (cause instanceof CancelledException) {
 				assertEquals(JGitText.get().operationCanceled,
 						cause.getMessage());
-			} else if (cause instanceof IOException) {
-				Throwable cause2 = cause.getCause();
-				assertTrue(cause2 instanceof InterruptedException
-						|| cause2 instanceof ExecutionException);
+			} else if (cause instanceof ClosedByInterruptException) {
+				// thread was interrupted
 			} else {
 				fail("unexpected exception " + e);
 			}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
index 111a4f3..502262a5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
@@ -1740,7 +1740,7 @@ private class PidLock implements AutoCloseable {
 			pidFile = repo.getDirectory().toPath().resolve(GC_PID);
 		}
 
-		boolean lock() {
+		boolean lock() throws IOException {
 			if (Files.exists(pidFile)) {
 				Instant mtime = FS.DETECTED
 						.lastModifiedInstant(pidFile.toFile());
@@ -1758,8 +1758,8 @@ boolean lock() {
 				f = new RandomAccessFile(pidFile.toFile(), "rw"); //$NON-NLS-1$
 				channel = f.getChannel();
 				lock = channel.tryLock();
-				if (lock == null) {
-					failedToLock();
+				if (lock == null || !lock.isValid()) {
+					gcAlreadyRunning();
 					return false;
 				}
 				channel.write(ByteBuffer
@@ -1779,7 +1779,7 @@ boolean lock() {
 									JGitText.get().closePidLockFailed, pidFile),
 							e1);
 				}
-				return false;
+				throw e;
 			}
 			return true;
 		}
@@ -1837,7 +1837,7 @@ private String getHostName() {
 		public void close() {
 			boolean wasLocked = false;
 			try {
-				if (lock != null) {
+				if (lock != null && lock.isValid()) {
 					lock.release();
 					wasLocked = true;
 				}