-
Notifications
You must be signed in to change notification settings - Fork 7.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
java.lang.Error is not propagated through onError (2.x) #5818
Comments
This is by design. Most |
Thanks for a quick reply. |
It should be rethrown which will end up in the Thread's uncaught exception handler. Which exact case did signal an
Catch |
with direct subclasses of public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
Single.fromCallable(() -> { throw new IOError(new RuntimeException("FATAL!")); })
.subscribeOn(Schedulers.computation())
.subscribe(v -> {
latch.countDown();
System.out.println(v);
},
e -> {
latch.countDown();
throw new RuntimeException(e);
});
latch.await();
System.out.println("Finished");
} You can also try public static void main(String[] args) throws InterruptedException {
Thread.UncaughtExceptionHandler handler = (t, e) -> {
System.err.println("Uncaught exception!");
System.err.println(e);
};
Scheduler scheduler = Schedulers.from(Executors.newFixedThreadPool(10, r -> {
Thread thread = new Thread(r);
thread.setUncaughtExceptionHandler(handler);
return thread;
}));
CountDownLatch latch = new CountDownLatch(1);
Single.fromCallable(() -> { throw new AbstractMethodError("FATAL!"); })
.subscribeOn(scheduler)
.subscribe(v -> {
latch.countDown();
System.out.println(v);
},
e -> {
latch.countDown();
throw new RuntimeException(e);
});
latch.await();
System.out.println("Finished");
} What do you mean by
Wrapping each method call in |
These are the fatal error classes that don't get propagated (also their subclasses):
Don't throw these programmatically. They quit the flow because they are considered fatal and unrecoverable errors. Trying to propagate them as errors will likely lead to more crashing. See #748 which prompted for the now established behavior.
try {
// your unreliable method calls here
} catch (VirtualMachineError ex) {
throw new RuntimeException(ex);
} But as stated above, when such exceptions are catched by RxJava, they are considered fatal and unrecoverable from the flow's perspective. It becomes unsafe to call any method on downstream. Imagine you have a |
I see your point. I agree with you completely on the point "don't throw error programatically" and we did not. If you are curious, the jdk bug is described in https://stackoverflow.com/questions/27031244/lambdaconversionexception-with-generics-jvm-bug and for Oracle's jdk it's reported to be fixed only in jdk9 https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8141508 I still not completely understand how to make application reliably crash on fatal errors, though, but thanks anyway for your help. |
not really a great solution to have important exceptions potentially go entirely unnoticed unless all consumers explicitly handle this. why not delegate to global error handler at least and make swallowing behaviour for those errors default, so at least it could be overridden via |
No. See the reasoning above. |
you provided other examples? |
I agree that those errors should terminate the flow unconditionally. but what's the reason for not invoking the global error handler and swallowing them entirely? |
RX Version: io.reactivex.rxjava2:rxjava:2.1.8
JDK Version Oracle 1.8.0_151
Summary: Observable, Single, Completable, etc do not always propagate errors (subclasses of java.lang.Error) and subsequently do not complete, which causes deadlocks and hanging.
Details: My colleagues and I found out that some types of errors within observable (as well as Single, Completable) do not call
Emitter::onError
. I was able to reproduce it with errors likeIllegalAccessError
,StackOverflowError
,OutOfMemoryError
, etc. But some errors do not cause hanging, e.g.IOError
.Originally, the bug was found because
Singe.merge()
was hanging on non-blocking method throwingjava.lang.NoSuchMethodError
due to a method reference to a generic type union (which is another story).Note, that if you
.subscribeOn(Schedulers.io())
the error is emitted downstream. Hanging occurs only when you.subscribeOn(Schedulers.computation())
or with a custom limited scheduler, e.g.Schedulers.from(Executors.newFixedThreadPool(50))
.How to reproduce:
I will be glad to provide any necessary additional information.
The text was updated successfully, but these errors were encountered: