FS.detectSymlinkSupport: fix a race
When >1 JGit clients are instantiated concurrently, they may try to create the same symlink at the same time. When that happens, the second thread will return an error (because the symlink already exists) and that `FS` instance will think that symlinks are not supported, causing havoc.motiejus-detectSymlinkSupport
parent
b1cc74b75b
commit
ab2d63322f
|
@ -32,6 +32,8 @@ import java.time.format.DateTimeFormatter;
|
|||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.eclipse.jgit.errors.CommandFailedException;
|
||||
import org.eclipse.jgit.junit.MockSystemReader;
|
||||
|
@ -195,6 +197,26 @@ public class FSTest {
|
|||
SystemReader.getInstance().getDefaultCharset().name());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrentSymlinkSupport()
|
||||
throws ExecutionException, InterruptedException {
|
||||
FS fs1 = FS.DETECTED;
|
||||
Assume.assumeTrue(fs1.supportsSymlinks());
|
||||
// 2 is somewhat reliable, 3 is very reliable.
|
||||
int numberOfThreads = 3;
|
||||
CompletableFuture<Boolean>[] futures = new CompletableFuture[numberOfThreads];
|
||||
for (int i = 0; i < numberOfThreads; i++) {
|
||||
futures[i] = CompletableFuture.supplyAsync(() -> {
|
||||
FS fs2 = fs1.newInstance();
|
||||
return fs2.supportsSymlinks();
|
||||
});
|
||||
}
|
||||
for (int i = 0; i < numberOfThreads; i++) {
|
||||
assertTrue(futures[i].get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testFsTimestampResolution() throws Exception {
|
||||
DateTimeFormatter formatter = DateTimeFormatter
|
||||
|
|
|
@ -1024,7 +1024,7 @@ public abstract class FS {
|
|||
File tempFile = null;
|
||||
try {
|
||||
tempFile = File.createTempFile("tempsymlinktarget", ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
File linkName = new File(tempFile.getParentFile(), "tempsymlink"); //$NON-NLS-1$
|
||||
File linkName = new File(tempFile.getPath() + "-thelink"); //$NON-NLS-1$
|
||||
createSymLink(linkName, tempFile.getPath());
|
||||
supportSymlinks = Boolean.TRUE;
|
||||
linkName.delete();
|
||||
|
|
Loading…
Reference in New Issue