You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by cs...@apache.org on 2024/06/06 10:31:23 UTC
(maven) branch master updated: [MNG-8066] Default exception handler does not handle recursion (#1558)
This is an automated email from the ASF dual-hosted git repository.
cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/master by this push:
new 9ce85ef4f4 [MNG-8066] Default exception handler does not handle recursion (#1558)
9ce85ef4f4 is described below
commit 9ce85ef4f4469287aae8a1e43e3d6960d41b746c
Author: Tamas Cservenak <ta...@cservenak.net>
AuthorDate: Thu Jun 6 12:31:03 2024 +0200
[MNG-8066] Default exception handler does not handle recursion (#1558)
If there is a recursion in throwable causes, Maven will hang forever, instead to return.
---
https://issues.apache.org/jira/browse/MNG-8066
---
.../maven/exception/DefaultExceptionHandler.java | 24 ++++++++++++++++------
.../exception/DefaultExceptionHandlerTest.java | 16 +++++++++++++++
2 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/maven-core/src/main/java/org/apache/maven/exception/DefaultExceptionHandler.java b/maven-core/src/main/java/org/apache/maven/exception/DefaultExceptionHandler.java
index b6c4e8cca5..059e1c8e17 100644
--- a/maven-core/src/main/java/org/apache/maven/exception/DefaultExceptionHandler.java
+++ b/maven-core/src/main/java/org/apache/maven/exception/DefaultExceptionHandler.java
@@ -25,7 +25,10 @@ import java.io.IOException;
import java.net.ConnectException;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.IdentityHashMap;
import java.util.List;
+import java.util.Set;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.model.building.ModelProblem;
@@ -88,13 +91,13 @@ Plugins:
@Named
@Singleton
public class DefaultExceptionHandler implements ExceptionHandler {
-
+ @Override
public ExceptionSummary handleException(Throwable exception) {
return handle("", exception);
}
private ExceptionSummary handle(String message, Throwable exception) {
- String reference = getReference(exception);
+ String reference = getReference(Collections.newSetFromMap(new IdentityHashMap<>()), exception);
List<ExceptionSummary> children = null;
@@ -156,8 +159,11 @@ public class DefaultExceptionHandler implements ExceptionHandler {
}
}
- private String getReference(Throwable exception) {
+ private String getReference(Set<Throwable> dejaVu, Throwable exception) {
String reference = "";
+ if (!dejaVu.add(exception)) {
+ return reference;
+ }
if (exception != null) {
if (exception instanceof MojoExecutionException) {
@@ -187,14 +193,14 @@ public class DefaultExceptionHandler implements ExceptionHandler {
}
if (reference == null || reference.isEmpty()) {
- reference = getReference(cause);
+ reference = getReference(dejaVu, cause);
}
if (reference == null || reference.isEmpty()) {
reference = exception.getClass().getSimpleName();
}
} else if (exception instanceof LifecycleExecutionException) {
- reference = getReference(exception.getCause());
+ reference = getReference(dejaVu, exception.getCause());
} else if (isNoteworthyException(exception)) {
reference = exception.getClass().getSimpleName();
}
@@ -222,7 +228,8 @@ public class DefaultExceptionHandler implements ExceptionHandler {
private String getMessage(String message, Throwable exception) {
String fullMessage = (message != null) ? message : "";
- // To break out of possible endless loop when getCause returns "this"
+ // To break out of possible endless loop when getCause returns "this", or dejaVu for n-level recursion (n>1)
+ Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>());
for (Throwable t = exception; t != null && t != t.getCause(); t = t.getCause()) {
String exceptionMessage = t.getMessage();
@@ -247,6 +254,11 @@ public class DefaultExceptionHandler implements ExceptionHandler {
} else if (!fullMessage.contains(exceptionMessage)) {
fullMessage = join(fullMessage, exceptionMessage);
}
+
+ if (!dejaVu.add(t)) {
+ fullMessage = join(fullMessage, "[CIRCULAR REFERENCE]");
+ break;
+ }
}
return fullMessage.trim();
diff --git a/maven-core/src/test/java/org/apache/maven/exception/DefaultExceptionHandlerTest.java b/maven-core/src/test/java/org/apache/maven/exception/DefaultExceptionHandlerTest.java
index f3f6075533..c9a84014d2 100644
--- a/maven-core/src/test/java/org/apache/maven/exception/DefaultExceptionHandlerTest.java
+++ b/maven-core/src/test/java/org/apache/maven/exception/DefaultExceptionHandlerTest.java
@@ -123,4 +123,20 @@ class DefaultExceptionHandlerTest {
String expectedReference = "http://cwiki.apache.org/confluence/display/MAVEN/PluginContainerException";
assertEquals(expectedReference, summary.getReference());
}
+
+ @Test
+ void testHandleExceptionSelfReferencing() {
+ RuntimeException boom3 = new RuntimeException("BOOM3");
+ RuntimeException boom2 = new RuntimeException("BOOM2", boom3);
+ RuntimeException boom1 = new RuntimeException("BOOM1", boom2);
+ boom3.initCause(boom1);
+
+ DefaultExceptionHandler handler = new DefaultExceptionHandler();
+ ExceptionSummary summary = handler.handleException(boom1);
+
+ assertEquals("BOOM1: BOOM2: BOOM3: [CIRCULAR REFERENCE]", summary.getMessage());
+ assertEquals("", summary.getReference());
+ assertEquals(0, summary.getChildren().size());
+ assertEquals(boom1, summary.getException());
+ }
}