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

ConcurrentModificationException in parallel build somewhere in p2 AbstractRepository #4709

Open
sratz opened this issue Feb 11, 2025 · 8 comments

Comments

@sratz
Copy link
Contributor

sratz commented Feb 11, 2025

I just got the following in a parallel build.

  • Tycho 4.0.11
  • -T 6

I am not sure whether this this is something that needs to be synchronized in the Tycho layer (or retried, similar to #3698?), or if this is an actual bug in P2, since AbstractRepositoryManager already uses a synchronized(repositoryLock) { ... }, and it still fails.

[ERROR] ConcurrentModificationException
java.util.ConcurrentModificationException
    at java.util.LinkedHashMap$LinkedHashIterator.nextNode (LinkedHashMap.java:1023)
    at java.util.LinkedHashMap$LinkedEntryIterator.next (LinkedHashMap.java:1058)
    at java.util.LinkedHashMap$LinkedEntryIterator.next (LinkedHashMap.java:1055)
    at org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties$UnmodifiableProperties.<init> (OrderedProperties.java:213)
    at org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties.unmodifiableProperties (OrderedProperties.java:37)
    at org.eclipse.equinox.p2.repository.spi.AbstractRepository.getProperties (AbstractRepository.java:110)
    at org.eclipse.equinox.internal.p2.repository.helpers.AbstractRepositoryManager.addRepository (AbstractRepositoryManager.java:132)
    at org.eclipse.equinox.internal.p2.repository.helpers.AbstractRepositoryManager.basicGetRepository (AbstractRepositoryManager.java:197)
    at org.eclipse.equinox.internal.p2.repository.helpers.AbstractRepositoryManager.loadRepository (AbstractRepositoryManager.java:678)
    at org.eclipse.equinox.internal.p2.artifact.repository.ArtifactRepositoryManager.loadRepository (ArtifactRepositoryManager.java:131)
    at org.eclipse.equinox.internal.p2.artifact.repository.ArtifactRepositoryManager.loadRepository (ArtifactRepositoryManager.java:125)
    at org.eclipse.tycho.p2maven.transport.P2MirrorDisablingArtifactRepositoryManager.loadRepository (P2MirrorDisablingArtifactRepositoryManager.java:94)
    at org.eclipse.tycho.p2maven.transport.RemoteArtifactRepositoryManager.lambda$loadRepository$1 (RemoteArtifactRepositoryManager.java:105)
    at org.eclipse.tycho.p2maven.transport.RemoteArtifactRepositoryManager.accessRepository (RemoteArtifactRepositoryManager.java:137)
    at org.eclipse.tycho.p2maven.transport.RemoteArtifactRepositoryManager.loadRepository (RemoteArtifactRepositoryManager.java:105)
    at org.eclipse.tycho.p2.repository.RepositoryArtifactProvider.loadRepository (RepositoryArtifactProvider.java:112)
    at org.eclipse.tycho.p2.repository.LazyArtifactRepository.getDelegate (LazyArtifactRepository.java:50)
    at org.eclipse.tycho.p2.repository.LazyArtifactRepository.contains (LazyArtifactRepository.java:87)
    at org.eclipse.tycho.p2.repository.RepositoryArtifactProvider.contains (RepositoryArtifactProvider.java:133)
    at org.eclipse.tycho.p2.repository.MirroringArtifactProvider.isFileAlreadyAvailable (MirroringArtifactProvider.java:439)
    at org.eclipse.tycho.p2.repository.CompositeArtifactProvider.lambda$isFileAlreadyAvailable$0 (CompositeArtifactProvider.java:173)
    at java.util.stream.MatchOps$1MatchSink.accept (MatchOps.java:90)
    at java.util.Spliterators$ArraySpliterator.tryAdvance (Spliterators.java:1034)
    at java.util.stream.ReferencePipeline.forEachWithCancel (ReferencePipeline.java:129)
    at java.util.stream.AbstractPipeline.copyIntoWithCancel (AbstractPipeline.java:527)
    at java.util.stream.AbstractPipeline.copyInto (AbstractPipeline.java:513)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto (AbstractPipeline.java:499)
    at java.util.stream.MatchOps$MatchOp.evaluateSequential (MatchOps.java:230)
    at java.util.stream.MatchOps$MatchOp.evaluateSequential (MatchOps.java:196)
    at java.util.stream.AbstractPipeline.evaluate (AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.anyMatch (ReferencePipeline.java:632)
    at org.eclipse.tycho.p2.repository.CompositeArtifactProvider.isFileAlreadyAvailable (CompositeArtifactProvider.java:173)
    at org.eclipse.tycho.p2resolver.TargetPlatformBaseImpl.isFileAlreadyAvailable (TargetPlatformBaseImpl.java:200)
    at org.eclipse.tycho.p2resolver.PreliminaryTargetPlatformImpl.isFileAlreadyAvailable (PreliminaryTargetPlatformImpl.java:39)
    at org.eclipse.tycho.core.resolver.DefaultP2ResolutionResult.lambda$new$1 (DefaultP2ResolutionResult.java:56)
    at java.util.stream.ReferencePipeline$3$1.accept (ReferencePipeline.java:197)
    at java.util.HashMap$KeySpliterator.forEachRemaining (HashMap.java:1715)
    at java.util.stream.AbstractPipeline.copyInto (AbstractPipeline.java:509)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto (AbstractPipeline.java:499)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential (ReduceOps.java:921)
    at java.util.stream.AbstractPipeline.evaluate (AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect (ReferencePipeline.java:682)
    at org.eclipse.tycho.core.resolver.DefaultP2ResolutionResult.<init> (DefaultP2ResolutionResult.java:70)
    at org.eclipse.tycho.p2resolver.P2ResolverImpl.toResolutionResult (P2ResolverImpl.java:252)
    at org.eclipse.tycho.p2resolver.P2ResolverImpl.resolveDependencies (P2ResolverImpl.java:246)
    at org.eclipse.tycho.p2resolver.P2ResolverImpl.resolveTargetDependencies (P2ResolverImpl.java:124)
    at org.eclipse.tycho.p2resolver.P2DependencyResolver.doResolveDependencies (P2DependencyResolver.java:378)
    at org.eclipse.tycho.p2resolver.P2DependencyResolver.resolveDependencies (P2DependencyResolver.java:328)
    at org.eclipse.tycho.core.osgitools.AbstractTychoProject.lambda$getDependencyArtifacts$0 (AbstractTychoProject.java:92)
    at org.eclipse.tycho.core.osgitools.DefaultReactorProject$LazyValue.get (DefaultReactorProject.java:307)
    at org.eclipse.tycho.core.osgitools.DefaultReactorProject.computeContextValue (DefaultReactorProject.java:200)
    at org.eclipse.tycho.core.osgitools.AbstractTychoProject.getDependencyArtifacts (AbstractTychoProject.java:82)
    at org.eclipse.tycho.core.resolver.DefaultTychoResolver.resolveProject (DefaultTychoResolver.java:98)
    at org.eclipse.tycho.core.maven.TychoProjectExecutionListener.beforeProjectLifecycleExecution (TychoProjectExecutionListener.java:111)
    at org.apache.maven.lifecycle.internal.CompoundProjectExecutionListener.beforeProjectLifecycleExecution (CompoundProjectExecutionListener.java:42)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:103)
    at io.takari.maven.builder.smart.SmartBuilderImpl.buildProject (SmartBuilderImpl.java:206)
    at io.takari.maven.builder.smart.SmartBuilderImpl$ProjectBuildTask.run (SmartBuilderImpl.java:71)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:572)
    at java.util.concurrent.FutureTask.run (FutureTask.java:317)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1144)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:642)
    at java.lang.Thread.run (Thread.java:1583)
[ERROR] com.sap.adt.sapgui.embedding: null: ConcurrentModificationException
java.lang.RuntimeException: com.sap.adt.sapgui.embedding: null
    at io.takari.maven.builder.smart.SmartBuilderImpl.buildProject (SmartBuilderImpl.java:209)
    at io.takari.maven.builder.smart.SmartBuilderImpl$ProjectBuildTask.run (SmartBuilderImpl.java:71)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:572)
    at java.util.concurrent.FutureTask.run (FutureTask.java:317)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1144)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:642)
    at java.lang.Thread.run (Thread.java:1583)
Caused by: java.util.ConcurrentModificationException
    at java.util.LinkedHashMap$LinkedHashIterator.nextNode (LinkedHashMap.java:1023)
    at java.util.LinkedHashMap$LinkedEntryIterator.next (LinkedHashMap.java:1058)
    at java.util.LinkedHashMap$LinkedEntryIterator.next (LinkedHashMap.java:1055)
    at org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties$UnmodifiableProperties.<init> (OrderedProperties.java:213)
    at org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties.unmodifiableProperties (OrderedProperties.java:37)
    at org.eclipse.equinox.p2.repository.spi.AbstractRepository.getProperties (AbstractRepository.java:110)
    at org.eclipse.equinox.internal.p2.repository.helpers.AbstractRepositoryManager.addRepository (AbstractRepositoryManager.java:132)
    at org.eclipse.equinox.internal.p2.repository.helpers.AbstractRepositoryManager.basicGetRepository (AbstractRepositoryManager.java:197)
    at org.eclipse.equinox.internal.p2.repository.helpers.AbstractRepositoryManager.loadRepository (AbstractRepositoryManager.java:678)
    at org.eclipse.equinox.internal.p2.artifact.repository.ArtifactRepositoryManager.loadRepository (ArtifactRepositoryManager.java:131)
    at org.eclipse.equinox.internal.p2.artifact.repository.ArtifactRepositoryManager.loadRepository (ArtifactRepositoryManager.java:125)
    at org.eclipse.tycho.p2maven.transport.P2MirrorDisablingArtifactRepositoryManager.loadRepository (P2MirrorDisablingArtifactRepositoryManager.java:94)
    at org.eclipse.tycho.p2maven.transport.RemoteArtifactRepositoryManager.lambda$loadRepository$1 (RemoteArtifactRepositoryManager.java:105)
    at org.eclipse.tycho.p2maven.transport.RemoteArtifactRepositoryManager.accessRepository (RemoteArtifactRepositoryManager.java:137)
    at org.eclipse.tycho.p2maven.transport.RemoteArtifactRepositoryManager.loadRepository (RemoteArtifactRepositoryManager.java:105)
    at org.eclipse.tycho.p2.repository.RepositoryArtifactProvider.loadRepository (RepositoryArtifactProvider.java:112)
    at org.eclipse.tycho.p2.repository.LazyArtifactRepository.getDelegate (LazyArtifactRepository.java:50)
    at org.eclipse.tycho.p2.repository.LazyArtifactRepository.contains (LazyArtifactRepository.java:87)
    at org.eclipse.tycho.p2.repository.RepositoryArtifactProvider.contains (RepositoryArtifactProvider.java:133)
    at org.eclipse.tycho.p2.repository.MirroringArtifactProvider.isFileAlreadyAvailable (MirroringArtifactProvider.java:439)
    at org.eclipse.tycho.p2.repository.CompositeArtifactProvider.lambda$isFileAlreadyAvailable$0 (CompositeArtifactProvider.java:173)
    at java.util.stream.MatchOps$1MatchSink.accept (MatchOps.java:90)
    at java.util.Spliterators$ArraySpliterator.tryAdvance (Spliterators.java:1034)
    at java.util.stream.ReferencePipeline.forEachWithCancel (ReferencePipeline.java:129)
    at java.util.stream.AbstractPipeline.copyIntoWithCancel (AbstractPipeline.java:527)
    at java.util.stream.AbstractPipeline.copyInto (AbstractPipeline.java:513)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto (AbstractPipeline.java:499)
    at java.util.stream.MatchOps$MatchOp.evaluateSequential (MatchOps.java:230)
    at java.util.stream.MatchOps$MatchOp.evaluateSequential (MatchOps.java:196)
    at java.util.stream.AbstractPipeline.evaluate (AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.anyMatch (ReferencePipeline.java:632)
    at org.eclipse.tycho.p2.repository.CompositeArtifactProvider.isFileAlreadyAvailable (CompositeArtifactProvider.java:173)
    at org.eclipse.tycho.p2resolver.TargetPlatformBaseImpl.isFileAlreadyAvailable (TargetPlatformBaseImpl.java:200)
    at org.eclipse.tycho.p2resolver.PreliminaryTargetPlatformImpl.isFileAlreadyAvailable (PreliminaryTargetPlatformImpl.java:39)
    at org.eclipse.tycho.core.resolver.DefaultP2ResolutionResult.lambda$new$1 (DefaultP2ResolutionResult.java:56)
    at java.util.stream.ReferencePipeline$3$1.accept (ReferencePipeline.java:197)
    at java.util.HashMap$KeySpliterator.forEachRemaining (HashMap.java:1715)
    at java.util.stream.AbstractPipeline.copyInto (AbstractPipeline.java:509)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto (AbstractPipeline.java:499)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential (ReduceOps.java:921)
    at java.util.stream.AbstractPipeline.evaluate (AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect (ReferencePipeline.java:682)
    at org.eclipse.tycho.core.resolver.DefaultP2ResolutionResult.<init> (DefaultP2ResolutionResult.java:70)
    at org.eclipse.tycho.p2resolver.P2ResolverImpl.toResolutionResult (P2ResolverImpl.java:252)
    at org.eclipse.tycho.p2resolver.P2ResolverImpl.resolveDependencies (P2ResolverImpl.java:246)
    at org.eclipse.tycho.p2resolver.P2ResolverImpl.resolveTargetDependencies (P2ResolverImpl.java:124)
    at org.eclipse.tycho.p2resolver.P2DependencyResolver.doResolveDependencies (P2DependencyResolver.java:378)
    at org.eclipse.tycho.p2resolver.P2DependencyResolver.resolveDependencies (P2DependencyResolver.java:328)
    at org.eclipse.tycho.core.osgitools.AbstractTychoProject.lambda$getDependencyArtifacts$0 (AbstractTychoProject.java:92)
    at org.eclipse.tycho.core.osgitools.DefaultReactorProject$LazyValue.get (DefaultReactorProject.java:307)
    at org.eclipse.tycho.core.osgitools.DefaultReactorProject.computeContextValue (DefaultReactorProject.java:200)
    at org.eclipse.tycho.core.osgitools.AbstractTychoProject.getDependencyArtifacts (AbstractTychoProject.java:82)
    at org.eclipse.tycho.core.resolver.DefaultTychoResolver.resolveProject (DefaultTychoResolver.java:98)
    at org.eclipse.tycho.core.maven.TychoProjectExecutionListener.beforeProjectLifecycleExecution (TychoProjectExecutionListener.java:111)
    at org.apache.maven.lifecycle.internal.CompoundProjectExecutionListener.beforeProjectLifecycleExecution (CompoundProjectExecutionListener.java:42)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:103)
    at io.takari.maven.builder.smart.SmartBuilderImpl.buildProject (SmartBuilderImpl.java:206)
    at io.takari.maven.builder.smart.SmartBuilderImpl$ProjectBuildTask.run (SmartBuilderImpl.java:71)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:572)
    at java.util.concurrent.FutureTask.run (FutureTask.java:317)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1144)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:642)
    at java.lang.Thread.run (Thread.java:1583)
@laeubi
Copy link
Member

laeubi commented Feb 11, 2025

As far as I have checked this is all properly synchronized. Nevertheless it does not protect from reentrant calls from the same thread.

Also properties is passed in from the constructor, so if one would pass an instance of properties that is also used in other threads this is something that could cause this, the same is true for AbstractRepository.setProperties(Map<String, String>).

SO I think one must carefully review all call sites if they probably are problematic here and then fix in either P2 or Tycho.

@merks
Copy link
Contributor

merks commented Feb 12, 2025

Note that the constructor copies the map:

Image

And while this this is synchronized it does not copy the map:

	protected synchronized void setProperties(Map<String, String> properties) {
		this.properties = properties;
	}

Probably it should clean the map and put all the new entries. It should not replace the OrderedMap I think.

Probably this should be synchronized because it's the only method that access the properties field but isn't synchronized:

	@Override
	public String getProperty(String key) {
		return properties.get(key);
	}

@merks
Copy link
Contributor

merks commented Feb 12, 2025

This seems to be involved though not clear to me what is modifying the properties of the delegate:

Image

@laeubi
Copy link
Member

laeubi commented Feb 12, 2025

This seems to be involved though not clear to me what is modifying the properties of the delegate:

I think it won't hurt to add an explicit Map.copyOf(...) here... even though it actually should already be a copy anyways...

@merks
Copy link
Contributor

merks commented Feb 12, 2025

I really don't like that in p2 the OrderedMap is replaced with some arbitrary map that can be modified elsewhere and thereby bypass the synchronization guards. I also think that getProperty not being synchronized is simply an oversight. If those were both fixed, I'm not sure anything would need to be done in Tycho. Or?

@laeubi
Copy link
Member

laeubi commented Feb 12, 2025

I really don't like that in p2 the OrderedMap is replaced with some arbitrary map that can be modified elsewhere and thereby bypass the synchronization guards.

It might be by intention... somewhere ... in any case I think its worth to try change that in P2 and see if any tests fail, if not merge it today and see if anything else fails during M3 testing.

I also think that getProperty not being synchronized is simply an oversight.

I don't think it is that critical, but would not harm to do so

I'm not sure anything would need to be done in Tycho.

The only think is if we want to change something we should do it now so Tycho not needs to wait for just another release :-)

merks added a commit to merks/p2 that referenced this issue Feb 12, 2025
- Make AbstractRepository.properties final.
- Modify AbstractRepository.setProperties to do a clear and a putAll.
- Make the only method that accesses AbstractRepository.properties
without synchronization, AbstractRepository.getProperty(String), also be
synchronized.

eclipse-tycho/tycho#4709
merks added a commit to eclipse-equinox/p2 that referenced this issue Feb 12, 2025
- Make AbstractRepository.properties final.
- Modify AbstractRepository.setProperties to do a clear and a putAll.
- Make the only method that accesses AbstractRepository.properties
without synchronization, AbstractRepository.getProperty(String), also be
synchronized.

eclipse-tycho/tycho#4709
@sratz
Copy link
Contributor Author

sratz commented Feb 13, 2025

Ensure that AbstractRepository.properties cannot be replaced eclipse-equinox/p2#689

Thanks, @merks!

I'm not sure anything would need to be done in Tycho.

The only think is if we want to change something we should do it now so Tycho not needs to wait for just another release :-)

Hmm, 2025-03 isn't that far away, so unless there's an obvious way to also synchronize inside Tycho layer, I think waiting for the new p2 is good enough. It's the first time I've seen this particular error in our build which runs almost daily.

@laeubi
Copy link
Member

laeubi commented Feb 13, 2025

Yes this will hopefully be fixed with next eclipse release and I plan to do a new release timely after maven artifacts are published and integrated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants