-
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
ScheduledAction Swallows Errors #1682
Comments
I've been researching this and there isn't a whole lot of choice in what to do when an Exception is thrown on a random I can't throw the exception anywhere else as the whole issue here is an unhandled exception being thrown. Thus, I'm going to catch the exceptions in This is an edge case that an app should not allow ... and the reason why Observables propagate errors as events ... to avoid this very case, so seeing these types of messages in log output signals a "bad thing" that should be resolved. This would NOT be good for system performance to allow these types of errors to be logged, but I feel this is far better to yell and scream about bad code rather than silently swallowing errors as it does now. |
An error such as this will be printed:
|
If an exception is thrown on a thread then we can't do anything with it so will log out to System.err. Fixes ReactiveX#1682 ScheduledAction Swallows Errors
I have merged the change. If anyone can suggest a better approach that would be great, please let me know here. |
Best of the worst. |
The added logging is nice, but why not continue throwing the error if it's fatal (like |
@dlew how would you solve this differently? The error is occurring on a separate thread, so the most violent death that can occur is killing that thread inside the ThreadPoolExecutor. The error can not propagate to the The public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex); // <------------- THIS IS WHERE THE EXCEPTION GOES
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
} One can use The only alternative I can think of is to reverse schedule events up the Observable chain, like having an If you can submit a pull request that offers a better solution I'd appreciate that. |
Thanks, I understand the problem a lot better now. I'll have to think on it; not sure there is a good solution. |
I know this isn't possible for even 1.0 but could |
A calling thread could not get a reference, as There is no issue catching the exception on the child thread, it's what to do with it that is the question. |
There is a related discussion here: #969 I haven't checked in a while, but IIRC part of the issue was that some operators like ObserveOn weren't forwarding errors? |
ObserveOn propagates errors downstream. We just can't send them upstream across thread boundaries. |
It would be great if we could add another plugin that gets called in place of the |
Would you prefer that over this:
I've never that so have no idea how it behaves especially with thread pools. |
No, you're right, we can just use the built-in handler mechanism directly. We go directly I'll get a PR together. |
That sounds good, since then we are free to add listeners at any of the 3 levels, but just registering the default global listener (most likely) will still work and it will propagate to it. http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.UncaughtExceptionHandler.html
Thanks for bringing this to my attention @loganj I honestly wasn't even aware of this capability in the JVM and my use cases don't generally result in uncaught exceptions so I hadn't ever gone looking for it. |
No problem, we're really good at making exceptions happen. I'm basically done, but not sure if I should I apply the same handling to Schedulers that don't use ScheduledAction. ExecutorScheduler seems to need it. What about ImmediateScheduler and TrampolineScheduler? Do people rely on their current throwing behavior? Is that behavior contractual? |
I have not tried this issue on TrampolineScheduler but that may be okay as it's all on the same thread. ExecutorScheduler probably does need this, but let's get it solved for |
Instead of swallowing unhandled errors, ExecutorScheduler delivers them to the executing thread's UncaughtExceptionHandler. This addresses the same issue as ReactiveX#1682, but for ExecutorScheduler which does not used ScheduledAction.
ScheduledAction (used by
observeOn
and other things doing scheduling) swallows errors becauseFutureTask.run()
swallows errors inside aFuture
.This means something like
OnErrorNotImplemented
on theSubscriber
side of anobserveOn
will throw and be swallowed and everything will fail silently.The following code fails silently:
The text was updated successfully, but these errors were encountered: