Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make synchronized #4923

Closed
wants to merge 1 commit into from
Closed

make synchronized #4923

wants to merge 1 commit into from

Conversation

jeremylong
Copy link
Owner

Given run 3231291349 there is a ConcurrentModificationException:

java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification (ArrayList.java:911)
    at java.util.ArrayList$Itr.next (ArrayList.java:861)
    at org.owasp.dependencycheck.analyzer.AbstractSuppressionAnalyzer.analyzeDependency (AbstractSuppressionAnalyzer.java:136)
    at org.owasp.dependencycheck.analyzer.CpeSuppressionAnalyzer.analyzeDependency (CpeSuppressionAnalyzer.java:91)
    at org.owasp.dependencycheck.analyzer.AbstractAnalyzer.analyze (AbstractAnalyzer.java:131)
    at org.owasp.dependencycheck.analyzer.CPEAnalyzer.determineIdentifiers (CPEAnalyzer.java:960)
    at org.owasp.dependencycheck.analyzer.CPEAnalyzer.determineCPE (CPEAnalyzer.java:298)
    at org.owasp.dependencycheck.analyzer.CPEAnalyzer.analyzeDependency (CPEAnalyzer.java:779)
    at org.owasp.dependencycheck.analyzer.AbstractAnalyzer.analyze (AbstractAnalyzer.java:131)
    at org.owasp.dependencycheck.AnalysisTask.call (AnalysisTask.java:88)
    at org.owasp.dependencycheck.AnalysisTask.call (AnalysisTask.java:37)
    at java.util.concurrent.FutureTask.run (FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:624)
    at java.lang.Thread.run (Thread.java:750)

This PR adds synchronization...

@boring-cyborg boring-cyborg bot added the core changes to core label Oct 12, 2022
@jeremylong jeremylong added this to the 7.2.2 milestone Oct 12, 2022
@aikebah
Copy link
Collaborator

aikebah commented Oct 12, 2022

Given run 3231291349 there is a ConcurrentModificationException:

...

This PR adds synchronization...

Making analyzeDependency a synchronized method would not prevent the rules list to be modified when analysis traverses it, so I don't think making this method synchronized would do any good (the method reads the list, but does not modify it).
The modification of the rules (likely for this case: resets (list.clear()) in testcases) should be guarded by synchronisation and the same synchronisation object should be used within analyzeDependency to prevent it running concurrently to list-modifying code.

@jeremylong
Copy link
Owner Author

@aikebah what I believe is happening is during execution on multi-module project - while module 1 is cycling over the suppression rules, module 2 triggers a reload on the suppression rules which causes module 1's execution to throw the concurrent modification exception.

We have only been seeing this error in the CI on 690-threadsafety - which is there to identify this type of issue.

@jeremylong
Copy link
Owner Author

So either we synchronize on the rules or we create a copy of the rules:

protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
        List<SuppressionRule> suppressions = new ArrayList<>();
        suppressions.addAll(rules.list());
        if (suppressions.isEmpty()) {
            return;
        }
        for (SuppressionRule rule : suppressions) {
...

Thoughts?

@aikebah
Copy link
Collaborator

aikebah commented Oct 13, 2022

calling analyzeDependency happens a lot (once for each dependency), so copying the rules for each dependency would likely cause a tremendous amount of wasted CPU cycles and memory. My gut feel would be that we're best off by changing the rules to a synchronized List and synchronizing the iteration on that same list as per https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedList-java.util.List-

@aikebah
Copy link
Collaborator

aikebah commented Oct 13, 2022

at second thought: why would the same JVM reload it... I think the answer lies in 'different submodule with different suppressionFile configuration', which would mean we want to fully prevent that reload from happening while the entire analysis runs. That would call for a ThreadLocal rules list instead of a singleton, assuming that we process the entire analysis of a certain module within the same thread.

@jeremylong
Copy link
Owner Author

The reload is happening even with the same suppression file - 690-threadsafety does not contain any local suppression files. I think ThreadLocal rules are going to be the best option.

@jeremylong
Copy link
Owner Author

After thinking through this a bit more - I'm going to remove the singleton on the rules and add a new mechanism to store objects throughout the execution.

@jeremylong jeremylong closed this Oct 18, 2022
@jeremylong jeremylong removed this from the 7.2.2 milestone Oct 19, 2022
@jeremylong jeremylong deleted the concurrentModification branch October 20, 2022 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core changes to core
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants