Skip to content

Commit 5e3f6c4

Browse files
pyricauakarnokd
authored andcommitted
#4737 Error when tracking exception with unknown cause (#4740)
1 parent 61a5976 commit 5e3f6c4

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

src/main/java/rx/exceptions/AssemblyStackTraceException.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,15 @@ public void attachTo(Throwable exception) {
5252

5353
for (;;) {
5454
if (exception.getCause() == null) {
55-
exception.initCause(this);
55+
try {
56+
exception.initCause(this);
57+
} catch (IllegalStateException e) {
58+
RxJavaHooks.onError(new RuntimeException(
59+
"Received an exception with a cause set to null, instead of being unset."
60+
+ " To fix this, look down the chain of causes. The last exception had"
61+
+ " a cause explicitly set to null. It should be unset instead.",
62+
exception));
63+
}
5664
return;
5765
}
5866

src/test/java/rx/plugins/RxJavaHooksTest.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
import java.util.concurrent.CountDownLatch;
2424
import java.util.concurrent.atomic.AtomicInteger;
2525

26+
import java.util.concurrent.atomic.AtomicReference;
2627
import org.junit.Test;
2728

29+
import org.mockito.Mockito;
2830
import rx.*;
2931
import rx.Observable;
3032
import rx.Scheduler.Worker;
@@ -39,6 +41,12 @@
3941

4042
public class RxJavaHooksTest {
4143

44+
public static class TestExceptionWithUnknownCause extends RuntimeException {
45+
TestExceptionWithUnknownCause() {
46+
super((Throwable) null);
47+
}
48+
}
49+
4250
static Observable<Integer> createObservable() {
4351
return Observable.range(1, 5).map(new Func1<Integer, Integer>() {
4452
@Override
@@ -48,6 +56,15 @@ public Integer call(Integer t) {
4856
});
4957
}
5058

59+
static Observable<Integer> createObservableThrowingUnknownCause() {
60+
return Observable.range(1, 5).map(new Func1<Integer, Integer>() {
61+
@Override
62+
public Integer call(Integer t) {
63+
throw new TestExceptionWithUnknownCause();
64+
}
65+
});
66+
}
67+
5168
@Test
5269
public void constructorShouldBePrivate() {
5370
TestUtil.checkUtilityClass(RxJavaHooks.class);
@@ -89,6 +106,31 @@ public void assemblyTrackingObservable() {
89106
}
90107
}
91108

109+
@Test
110+
public void assemblyTrackingObservableUnknownCause() {
111+
RxJavaHooks.enableAssemblyTracking();
112+
try {
113+
final AtomicReference<Throwable> onErrorThrowableRef = new AtomicReference<Throwable>();
114+
RxJavaHooks.setOnError(new Action1<Throwable>() {
115+
@Override
116+
public void call(Throwable throwable) {
117+
onErrorThrowableRef.set(throwable);
118+
}
119+
});
120+
TestSubscriber<Integer> ts = TestSubscriber.create();
121+
122+
createObservableThrowingUnknownCause().subscribe(ts);
123+
124+
ts.assertError(TestExceptionWithUnknownCause.class);
125+
126+
Throwable receivedError = onErrorThrowableRef.get();
127+
assertNotNull(receivedError);
128+
assertTrue(receivedError.getMessage().contains("cause set to null"));
129+
} finally {
130+
RxJavaHooks.reset();
131+
}
132+
}
133+
92134
static Single<Integer> createSingle() {
93135
return Single.just(1).map(new Func1<Integer, Integer>() {
94136
@Override

0 commit comments

Comments
 (0)