Skip to content

Commit 66c82b0

Browse files
zsxwingstevegury
authored andcommitted
1.x: Use the correct Throwable to set the cause for CompositeException (#3977)
The cause of #3679 is we use a wrong Throwable (its cause has been set) to set the cause and `initCause` will throw an exception. Hence, the cause chain is not created correctly. In this PR, it searches the root cause (which doesn't have a cause) and use it to call `initCause`.
1 parent 271c83b commit 66c82b0

File tree

2 files changed

+62
-4
lines changed

2 files changed

+62
-4
lines changed

src/main/java/rx/exceptions/CompositeException.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,12 @@ public synchronized Throwable getCause() {
147147
// we now have 'e' as the last in the chain
148148
try {
149149
chain.initCause(e);
150-
chain = chain.getCause();
151150
} catch (Throwable t) {
152151
// ignore
153152
// the javadocs say that some Throwables (depending on how they're made) will never
154153
// let me call initCause without blowing up even if it returns null
155-
chain = e;
156154
}
155+
chain = getRootCause(chain);
157156
}
158157
cause = _cause;
159158
}
@@ -280,17 +279,39 @@ public String getMessage() {
280279
private List<Throwable> getListOfCauses(Throwable ex) {
281280
List<Throwable> list = new ArrayList<Throwable>();
282281
Throwable root = ex.getCause();
283-
if (root == null) {
282+
if (root == null || root == ex) {
284283
return list;
285284
} else {
286285
while(true) {
287286
list.add(root);
288-
if (root.getCause() == null) {
287+
Throwable cause = root.getCause();
288+
if (cause == null || cause == root) {
289289
return list;
290290
} else {
291291
root = root.getCause();
292292
}
293293
}
294294
}
295295
}
296+
297+
/**
298+
* Returns the root cause of {@code e}. If {@code e.getCause()} returns {@null} or {@code e}, just return {@code e} itself.
299+
*
300+
* @param e the {@link Throwable} {@code e}.
301+
* @return The root cause of {@code e}. If {@code e.getCause()} returns {@null} or {@code e}, just return {@code e} itself.
302+
*/
303+
private Throwable getRootCause(Throwable e) {
304+
Throwable root = e.getCause();
305+
if (root == null || root == e) {
306+
return e;
307+
} else {
308+
while(true) {
309+
Throwable cause = root.getCause();
310+
if (cause == null || cause == root) {
311+
return root;
312+
}
313+
root = root.getCause();
314+
}
315+
}
316+
}
296317
}

src/test/java/rx/exceptions/CompositeExceptionTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828

2929
import org.junit.Test;
3030

31+
import rx.exceptions.CompositeException.CompositeExceptionCausalChain;
32+
3133
public class CompositeExceptionTest {
3234

3335
private final Throwable ex1 = new Throwable("Ex1");
@@ -239,4 +241,39 @@ public void messageVarargs() {
239241
CompositeException compositeException = new CompositeException(ex1, ex2, ex3);
240242
assertEquals("3 exceptions occurred. ", compositeException.getMessage());
241243
}
244+
245+
@Test
246+
public void complexCauses() {
247+
Throwable e1 = new Throwable("1");
248+
Throwable e2 = new Throwable("2");
249+
e1.initCause(e2);
250+
251+
Throwable e3 = new Throwable("3");
252+
Throwable e4 = new Throwable("4");
253+
e3.initCause(e4);
254+
255+
Throwable e5 = new Throwable("5");
256+
Throwable e6 = new Throwable("6");
257+
e5.initCause(e6);
258+
259+
CompositeException compositeException = new CompositeException(e1, e3, e5);
260+
assert(compositeException.getCause() instanceof CompositeExceptionCausalChain);
261+
262+
List<Throwable> causeChain = new ArrayList<Throwable>();
263+
Throwable cause = compositeException.getCause().getCause();
264+
while (cause != null) {
265+
causeChain.add(cause);
266+
cause = cause.getCause();
267+
}
268+
// The original relations
269+
//
270+
// e1 -> e2
271+
// e3 -> e4
272+
// e5 -> e6
273+
//
274+
// will be set to
275+
//
276+
// e1 -> e2 -> e3 -> e4 -> e5 -> e6
277+
assertEquals(Arrays.asList(e1, e2, e3, e4, e5, e6), causeChain);
278+
}
242279
}

0 commit comments

Comments
 (0)