Skip to content

Commit eea2afa

Browse files
committed
Remove cycles in CompositeException
1 parent 981ff6a commit eea2afa

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

rxjava-core/src/main/java/rx/exceptions/CompositeException.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ public final class CompositeException extends RuntimeException {
3838
public CompositeException(String messagePrefix, Collection<Throwable> errors) {
3939
List<Throwable> _exceptions = new ArrayList<Throwable>();
4040
CompositeExceptionCausalChain _cause = new CompositeExceptionCausalChain();
41-
int count = 0;
41+
int count = errors.size();
42+
errors = removeDuplicatedCauses(errors);
4243
for (Throwable e : errors) {
43-
count++;
4444
attachCallingThreadStack(_cause, e);
4545
_exceptions.add(e);
4646
}
@@ -73,6 +73,29 @@ public synchronized Throwable getCause() {
7373
return cause;
7474
}
7575

76+
private Collection<Throwable> removeDuplicatedCauses(Collection<Throwable> errors) {
77+
Set<Throwable> duplicated = new HashSet<Throwable>();
78+
for (Throwable cause : errors) {
79+
for (Throwable error : errors) {
80+
if(cause == error || duplicated.contains(error)) {
81+
continue;
82+
}
83+
while (error.getCause() != null) {
84+
error = error.getCause();
85+
if (error == cause) {
86+
duplicated.add(cause);
87+
break;
88+
}
89+
}
90+
}
91+
}
92+
if (!duplicated.isEmpty()) {
93+
errors = new ArrayList<Throwable>(errors);
94+
errors.removeAll(duplicated);
95+
}
96+
return errors;
97+
}
98+
7699
@SuppressWarnings("unused")
77100
// useful when debugging but don't want to make part of publicly supported API
78101
private static String getStackTraceAsString(StackTraceElement[] stack) {

rxjava-core/src/test/java/rx/exceptions/CompositeExceptionTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ public void testMultipleWithSameCause() {
5353

5454
}
5555

56+
@Test(timeout = 1000)
57+
public void testOneIsCauseOfAnother() {
58+
Throwable rootCause = new Throwable("RootCause");
59+
Throwable throwable = new Throwable("1", rootCause);
60+
CompositeException ce = new CompositeException("One is the cause of another",
61+
Arrays.asList(rootCause, throwable));
62+
63+
assertEquals(1, ce.getExceptions().size());
64+
}
65+
5666
@Test(timeout = 1000)
5767
public void testAttachCallingThreadStackParentThenChild() {
5868
CompositeException.attachCallingThreadStack(ex1, ex2);

0 commit comments

Comments
 (0)