aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-scanner-engine
diff options
context:
space:
mode:
Diffstat (limited to 'sonar-scanner-engine')
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploder.java23
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploderTest.java21
2 files changed, 43 insertions, 1 deletions
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploder.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploder.java
index 931a0727073..60da81630b1 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploder.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploder.java
@@ -22,6 +22,10 @@ package org.sonar.scanner.bootstrap;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.OverlappingFileLockException;
+
import org.apache.commons.io.FileUtils;
import org.sonar.api.utils.ZipUtils;
import org.sonar.core.platform.ExplodedPlugin;
@@ -54,7 +58,7 @@ public class ScannerPluginJarExploder extends PluginJarExploder {
File lockFile = new File(cachedFile.getParentFile(), filename + "_unzip.lock");
if (!destDir.exists()) {
try (FileOutputStream out = new FileOutputStream(lockFile)) {
- java.nio.channels.FileLock lock = out.getChannel().lock();
+ FileLock lock = createLockWithRetries(out.getChannel());
try {
// Recheck in case of concurrent processes
if (!destDir.exists()) {
@@ -71,4 +75,21 @@ public class ScannerPluginJarExploder extends PluginJarExploder {
}
return destDir;
}
+
+ private static FileLock createLockWithRetries(FileChannel channel) throws IOException {
+ int tryCount = 0;
+ while (tryCount++ < 10) {
+ try {
+ return channel.lock();
+ } catch (OverlappingFileLockException ofle) {
+ // ignore overlapping file exception
+ }
+ try {
+ Thread.sleep(200L * tryCount);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ throw new IOException("Unable to get lock after " + tryCount + " tries");
+ }
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploderTest.java
index 09f5aee57cd..d46d868c0a6 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploderTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploderTest.java
@@ -20,7 +20,9 @@
package org.sonar.scanner.bootstrap;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.nio.channels.FileLock;
import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.ClassRule;
@@ -30,6 +32,7 @@ import org.sonar.core.platform.ExplodedPlugin;
import org.sonar.core.platform.PluginInfo;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -72,6 +75,24 @@ public class ScannerPluginJarExploderTest {
assertThat(new File(jar.getParent(), "sonar-checkstyle-plugin-2.8.jar_unzip/org/sonar/plugins/checkstyle/CheckstyleVersion.class")).doesNotExist();
}
+ @Test
+ public void retry_on_locked_file() throws IOException {
+ File jar = loadFile("sonar-checkstyle-plugin-2.8.jar");
+ File lockFile = new File(jar.getParentFile(), jar.getName() + "_unzip.lock");
+ try (FileOutputStream out = new FileOutputStream(lockFile)) {
+ FileLock lock = out.getChannel().lock();
+ try {
+ PluginInfo pluginInfo = PluginInfo.create(jar);
+ assertThatExceptionOfType(IllegalStateException.class)
+ .isThrownBy(() -> underTest.explode(pluginInfo))
+ .withMessage("Fail to open plugin [checkstyle]: " + jar)
+ .withCauseExactlyInstanceOf(IOException.class);
+ } finally {
+ lock.release();
+ }
+ }
+ }
+
private File loadFile(String filename) throws IOException {
File src = FileUtils.toFile(getClass().getResource(getClass().getSimpleName() + "/" + filename));
File dest = new File(temp.newFolder(), filename);