forked from phoedos/pmd
[core] Fix IOException loading rulesets under concurrency
- Fixes #234 - When a single JVM runs multiple PMD instances under different threads, connections to PMD jars (and streams opened to read standard rulesets) are shared, causing race conditions where one thread may cause the other to close it's streams. This in tun produces IOExceptions. - This happens in Gradle when enabling parallel builds. I believe it can happen under Maven with -T1C too, but has not been able to reproduce it. - I take the chance to clean up classloader closing code, making it more concise and standard accross CLI and Ant.
This commit is contained in:
Juan Martín Sotuyo Dodero
committed by
Andreas Dangel
parent
88c2557f15
commit
dd103aae56
@ -275,6 +275,15 @@ public class PMD {
|
||||
return 0;
|
||||
} finally {
|
||||
Benchmarker.mark(Benchmark.Reporting, System.nanoTime() - reportStart, 0);
|
||||
|
||||
/*
|
||||
* Make sure it's our own classloader before attempting to close it....
|
||||
* Maven + Jacoco provide us with a cloaseable classloader that if closed
|
||||
* will throw a ClassNotFoundException.
|
||||
*/
|
||||
if (configuration.getClassLoader() instanceof ClasspathClassLoader) {
|
||||
IOUtil.tryCloseClassLoader(configuration.getClassLoader());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,10 +371,6 @@ public class PMD {
|
||||
} else {
|
||||
new MonoThreadProcessor(configuration).processFiles(ruleSetFactory, files, ctx, renderers);
|
||||
}
|
||||
|
||||
if (configuration.getClassLoader() instanceof ClasspathClassLoader) {
|
||||
IOUtil.tryCloseClassLoader(configuration.getClassLoader());
|
||||
}
|
||||
}
|
||||
|
||||
private static void sortFiles(final PMDConfiguration configuration, final List<DataSource> files) {
|
||||
|
@ -8,6 +8,7 @@ import net.sourceforge.pmd.RuleSetNotFoundException;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
@ -73,7 +74,20 @@ public final class ResourceLoader {
|
||||
connection.setReadTimeout(TIMEOUT);
|
||||
return connection.getInputStream();
|
||||
} catch (Exception e) {
|
||||
return loader.getResourceAsStream(name);
|
||||
try {
|
||||
/*
|
||||
* Don't use getResourceAsStream to void reusing connections between threads
|
||||
* See https://github.com/pmd/pmd/issues/234
|
||||
*/
|
||||
URL resource = loader.getResource(name);
|
||||
if (resource == null) {
|
||||
// Don't throw RuleSetNotFoundException, keep API compatibility
|
||||
return null;
|
||||
}
|
||||
return resource.openStream();
|
||||
} catch (IOException e1) {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new RuleSetNotFoundException("Can't find resource " + name + ". Make sure the resource is a valid file or URL or is on the CLASSPATH");
|
||||
|
Reference in New Issue
Block a user