michael-o commented on a change in pull request #627:
URL: https://github.com/apache/maven/pull/627#discussion_r761462096



##########
File path: 
maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java
##########
@@ -202,6 +210,80 @@ private void execute( MavenSession session, MojoExecution 
mojoExecution, Project
             }
         }
 
+        try ( ProjectLock lock = new ProjectLock( session, mojoDescriptor, 
aggregatorLock ) )
+        {
+            doExecute( session, mojoExecution, projectIndex, dependencyContext 
);
+        }
+    }
+
+    /**
+     * 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.
+     * We also lock on a given project to forbid a forked lifecycle to be 
executed concurrently with the project.
+     * TODO: ideally, the builder should take care of the ordering in a 
smarter way
+     * TODO: and concurrency issues fixed with MNG-7157
+     */
+    private static class ProjectLock implements AutoCloseable
+    {
+        final Lock acquiredAggregatorLock;
+        final Lock acquiredProjectLock;
+
+        ProjectLock( MavenSession session, MojoDescriptor mojoDescriptor, 
ReadWriteLock aggregatorLock )
+        {
+            if ( session.getRequest().getDegreeOfConcurrency() > 1 )
+            {
+                boolean aggregator = mojoDescriptor.isAggregator();
+                acquiredAggregatorLock = aggregator ? 
aggregatorLock.writeLock() : aggregatorLock.readLock();
+                acquiredProjectLock = getProjectLock( session );
+                acquiredAggregatorLock.lock();
+                acquiredProjectLock.lock();
+            }
+            else
+            {
+                acquiredAggregatorLock = null;
+                acquiredProjectLock = null;
+            }
+        }
+
+        @Override
+        public void close()
+        {
+            // release the lock in the reverse order of the acquisition
+            if ( acquiredProjectLock != null )
+            {
+                acquiredProjectLock.unlock();
+            }
+            if ( acquiredAggregatorLock != null )
+            {
+                acquiredAggregatorLock.unlock();
+            }
+        }
+
+        @SuppressWarnings( { "unchecked", "rawtypes" } )
+        private Lock getProjectLock( MavenSession session )
+        {
+            final Lock acquiredProjectLock;
+            SessionData data = session.getRepositorySession().getData();
+            Map<MavenProject, Lock> locks = ( Map ) data.get( 
ProjectLock.class );

Review comment:
       Right, since Session is shared among threads it should have it as well.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to