Rxjava: onError throws Exception after Flowable has been unsubscribed

Created on 28 Nov 2016  Â·  8Comments  Â·  Source: ReactiveX/RxJava

We have recently run up against this in RxJava 2.0.x, and I would like to clarify that this is the intended behaviour.

We are creating a Flowable that connects to a remote server and first needs to resolve the host. If host cannot be resolved, the UnknownHostException is propagated via onError:

val messages = Flowable.create<SourcedMessage>({ subscriber ->
        this.subscriber = subscriber
        try{
            addr = InetAddress.getByName(host)
        }catch (e:UnknownHostException){
            subscriber.onError(e)
            return@create
        }
       .....
}

This seems to work fine (we can use an invalid hostname and the retry logic wrapping it fires just as expected), but we have seen crashes in our crashlogs, where the Android app crashes with an uncaught UnknownHostException, which we did not expect.
The crash goes away as soon as we check subscriber.isCancelled before calling onError as in:

val messages = Flowable.create<SourcedMessage>({ subscriber ->
        this.subscriber = subscriber
        try{
            addr = InetAddress.getByName(host)
        }catch (e:UnknownHostException){
            if(!subscriber.isCancelled){
                    subscriber.onError(e)
            }
            return@create
        }
       .....
}

For what it matters the Flowable is further chained in a subscribeOn(Schedulers.io()).retryWhen().publish.refCount() chain that is observedOn and subscribed to on the AndroidScheduler.mainThread.

We would have expected the onError just being silently ignored after unsubscription (which occurs when the app goes into the background).
Maybe #4863 and #4807 are related too.

2.x Question

Most helpful comment

Sorry, mixed up the two versions. Otherwise, it is straightforward: you have to specify a callback Action1/Consumer:

// 1.x
RxJavaHooks.setOnError(e -> System.out.println(e.getMessage()));

// 2.x
RxJavaPlugins.setErrorHandler(e -> System.out.println(e.getMessage()));

All 8 comments

2.x reports undeliverable exceptions, such as ones that happen around a cancellation to the RxJavaPlugins error handler which then forwards it to the current thread's uncaught exception handler. On desktop, this just prints the stacktrace to the console whereas some Android setups treat it as a fatal exception and stop the app. I suggest installing a custom global error handler via RxJavaPlugins.setErrorHandler. I'll think about how to deal with the situation by using system parameters.

Thanks for clarification

@akarnokd, Can't find any guide to use RxJavaPlugins.setOnError in the wiki page https://github.com/ReactiveX/RxJava/wiki/Plugins

Sorry, mixed up the two versions. Otherwise, it is straightforward: you have to specify a callback Action1/Consumer:

// 1.x
RxJavaHooks.setOnError(e -> System.out.println(e.getMessage()));

// 2.x
RxJavaPlugins.setErrorHandler(e -> System.out.println(e.getMessage()));

In Android, Where do you recommend putting that block of code ? Thanks

@akarnokd Has this any side effects? Why is this not the default? If I understand correctly for example any call to .cache leads to the underlying observable not stopping when I'm unsubscribing.

Thus my App crashes by default when onError gets called after I have unsubscribed?

It prevents the app crashing when there's legitimate programming errors.

On Tue, Jan 10, 2017, 12:35 PM Paul Woitaschek notifications@github.com
wrote:

@akarnokd https://github.com/akarnokd Has this any side effects? Why is
this not the default? If I understand correctly for example any call to
.cache leads to the underlying observable not stopping when I'm
unsubscribing.

Thus my App crashes by default when onError gets called after I have
unsubscribed?

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/ReactiveX/RxJava/issues/4894#issuecomment-271690298,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAEEEUDcHEOT0irtBtitBs79A9dhty5Bks5rQ-uHgaJpZM4K-XLa
.

So with it I don't see legitimate programming erros and without it my App crashes without legitimate programming errors?

Is it possible to somehow get the old behaviour back so my app crashes only when I made a mistake?

Was this page helpful?
0 / 5 - 0 ratings