From c3553e27a57b9807111574a546ee21a31f6e147c Mon Sep 17 00:00:00 2001 From: Falko Modler Date: Sat, 9 Oct 2021 23:35:19 +0200 Subject: [PATCH] [MNG-7285] Block all other executions if executing aggregating mojo to fix MNG-6843 --- .../lifecycle/internal/MojoExecutor.java | 67 +++++++++++++------ 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java index b78f54dc42f..313478ca730 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java @@ -48,6 +48,9 @@ import java.util.Map; import java.util.Set; import java.util.TreeSet; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** *

@@ -76,8 +79,14 @@ public class MojoExecutor @Requirement private ExecutionEventCatapult eventCatapult; + private final Lock aggregatorReadLock; + private final Lock aggregatorWriteLock; + public MojoExecutor() { + ReadWriteLock aggregatorLock = new ReentrantReadWriteLock( true ); + aggregatorReadLock = aggregatorLock.readLock(); + aggregatorWriteLock = aggregatorLock.writeLock(); } public DependencyContext newDependencyContext( MavenSession session, List mojoExecutions ) @@ -197,37 +206,57 @@ private void execute( MavenSession session, MojoExecution mojoExecution, Project } } - List forkedProjects = executeForkedExecutions( mojoExecution, session, projectIndex ); - - ensureDependenciesAreResolved( mojoDescriptor, session, dependencyContext ); - - eventCatapult.fire( ExecutionEvent.Type.MojoStarted, session, mojoExecution ); + // Aggregating mojo executions (possibly) modify all MavenProjects, including those that are currently in use + // by concurrently running mojo executions. To prevent race conditions, an aggregating execution will block + // all other executions until finished. + Lock accquiredAggregatorLock = null; + if ( session.getRequest().getDegreeOfConcurrency() > 1 ) + { + accquiredAggregatorLock = mojoDescriptor.isAggregator() ? aggregatorWriteLock : aggregatorReadLock; + accquiredAggregatorLock.lock(); + } try { + List forkedProjects = executeForkedExecutions( mojoExecution, session, projectIndex ); + + ensureDependenciesAreResolved( mojoDescriptor, session, dependencyContext ); + + eventCatapult.fire( ExecutionEvent.Type.MojoStarted, session, mojoExecution ); + try { - pluginManager.executeMojo( session, mojoExecution ); + try + { + pluginManager.executeMojo( session, mojoExecution ); + } + catch ( MojoFailureException | PluginManagerException | PluginConfigurationException + | MojoExecutionException e ) + { + throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e ); + } + + eventCatapult.fire( ExecutionEvent.Type.MojoSucceeded, session, mojoExecution ); + } + catch ( LifecycleExecutionException e ) + { + eventCatapult.fire( ExecutionEvent.Type.MojoFailed, session, mojoExecution, e ); + + throw e; } - catch ( MojoFailureException | PluginManagerException | PluginConfigurationException - | MojoExecutionException e ) + finally { - throw new LifecycleExecutionException( mojoExecution, session.getCurrentProject(), e ); + for ( MavenProject forkedProject : forkedProjects ) + { + forkedProject.setExecutionProject( null ); + } } - - eventCatapult.fire( ExecutionEvent.Type.MojoSucceeded, session, mojoExecution ); - } - catch ( LifecycleExecutionException e ) - { - eventCatapult.fire( ExecutionEvent.Type.MojoFailed, session, mojoExecution, e ); - - throw e; } finally { - for ( MavenProject forkedProject : forkedProjects ) + if ( accquiredAggregatorLock != null ) { - forkedProject.setExecutionProject( null ); + accquiredAggregatorLock.unlock(); } } }