question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

2.x Exception unhandled after dispose()

See original GitHub issue

Exception unhandled if dispose() called. Did I used it in a wrong way ?

error stack:

java.lang.IllegalStateException: example
	at com.example.MyClass$2.apply(MyClass.java:31)
	at com.example.MyClass$2.apply(MyClass.java:23)
	at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.onNext(ObservableFlatMap.java:121)
	at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeOnObserver.onNext(ObservableSubscribeOn.java:63)
	at io.reactivex.internal.operators.observable.ObservableScalarXMap$ScalarDisposable.run(ObservableScalarXMap.java:246)
	at io.reactivex.internal.operators.observable.ObservableJust.subscribeActual(ObservableJust.java:35)
	at io.reactivex.Observable.subscribe(Observable.java:10179)
	at io.reactivex.internal.operators.observable.ObservableSubscribeOn$1.run(ObservableSubscribeOn.java:39)
	at io.reactivex.Scheduler$1.run(Scheduler.java:134)
	at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:59)
	at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Exception in thread "RxCachedThreadScheduler-1" java.lang.IllegalStateException: illegal
	at com.example.MyClass$2.apply(MyClass.java:31)
	at com.example.MyClass$2.apply(MyClass.java:23)
	at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.onNext(ObservableFlatMap.java:121)
	at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeOnObserver.onNext(ObservableSubscribeOn.java:63)
	at io.reactivex.internal.operators.observable.ObservableScalarXMap$ScalarDisposable.run(ObservableScalarXMap.java:246)
	at io.reactivex.internal.operators.observable.ObservableJust.subscribeActual(ObservableJust.java:35)
	at io.reactivex.Observable.subscribe(Observable.java:10179)
	at io.reactivex.internal.operators.observable.ObservableSubscribeOn$1.run(ObservableSubscribeOn.java:39)
	at io.reactivex.Scheduler$1.run(Scheduler.java:134)
	at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:59)
	at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

sample code:


public class MyClass {

    static Disposable disposable = null;

    public static void main(String[] args) {

        Observable.just(1)
                .subscribeOn(Schedulers.io())
                .flatMap(new Function<Integer, ObservableSource<Integer>>() {
                    @Override
                    public ObservableSource<Integer> apply(Integer integer) throws Exception {
                        long endTime = System.currentTimeMillis() + 500;
                        while (System.currentTimeMillis() < endTime) {
                        }
                        return Observable.error(new IllegalStateException("example"));
                    }
                })
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onError(Throwable e) {}

                    @Override
                    public void onComplete() {}

                    @Override
                    public void onSubscribe(Disposable d) {
                        disposable = d;
                    }

                    @Override
                    public void onNext(Integer integer) {}
                });


        try {
            Thread.sleep(50);
            disposable.dispose();
            Thread.sleep(500000);
        } catch (InterruptedException e) {
        }
    }
}

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:15 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
akarnokdcommented, Jul 4, 2018

This is by design, your Callable crashes and the downstream has disposed so the operator routes the error to the global error handler as it can’t know if the exception is relevant or not. Don’t crash into RxJava and consider using create() with emitter.tryOnError() instead.

You implemented BreakIfUnsubscribedFlowable incorrectly as it has no connection to the downstream’s dispose management. Btw you can achieve a similar disconnect effect via onTerminateDetach.

0reactions
ysyyorkcommented, Mar 9, 2022

I built a simple wrapper to resolve this issue

class SafeRxCallWrapper<T>(private val callback: () -> T) {
    fun runSingle(): Single<T> {
        return Single.create<T> { emitter ->
            try {
                val res = callback()
                emitter.onSuccess(res)
            } catch (th: Throwable) {
                emitter.tryOnError(th)
            }
        }
    }

    fun runObservable(): Observable<T> {
        return Observable.create<T> { emitter ->
            try {
                val res = callback()
                emitter.onNext(res)
            } catch (th: Throwable) {
                emitter.tryOnError(th)
            }
        }
    }

    fun runMaybe(): Maybe<T> {
        return Maybe.create<T> { emitter ->
            try {
                val res = callback()
                emitter.onSuccess(res)
            } catch (th: Throwable) {
                emitter.tryOnError(th)
            }
        }
    }

    fun runCompletable(): Completable {
        return Completable.create { emitter ->
            try {
                callback()
                emitter.onComplete()
            } catch (th: Throwable) {
                emitter.tryOnError(th)
            }
        }
    }
}

Then you can just do

val singleReturn = SafeRxCallWrapper<ClassA> {
    ClassA()
}.runSingle().subscribe({}, {})
Read more comments on GitHub >

github_iconTop Results From Across the Web

Flutter - Unhandled Exception: setState() called after dispose()
I tried to make a compass for a flutter app. This idea was to put an image of the compass on the camera...
Read more >
Flutter: Unhandled Exception: setState() called after dispose()
الله يسعدكم وصلوا على النبي واشتراك في القناةUnhandled Exception : setState() called after dispose (): SearchTapState#ff442(lifecycle state: ...
Read more >
Unhandled Exception: setState() called after dispose():
This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object...
Read more >
Memory management and patterns in ASP.NET Core
Learn how memory is managed in ASP.NET Core and how the garbage collector (GC) works.
Read more >
How to Properly Dispose of Resources In .NET Core - DZone
The proper way to fix it is to wrap things in a try/finally block to ensure “Dispose “will be called, even in the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found