"Interrupted while waiting for subscription to complete." in 1.0.0-rc8
See original GitHub issueDoesn’t happen on rc7. I can repro 100% of the time. Happens on both KitKat and Lollipop so I don’t think it’s specific to any particular Android version.
FATAL EXCEPTION: RxCachedThreadScheduler-4
Process: com.mycompany.myapp.development, PID: 4413
java.lang.IllegalStateException: Exception thrown on Scheduler.Worker thread. Add `onError` handling.
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:50)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: rx.exceptions.OnErrorNotImplementedException: Interrupted while waiting for subscription to complete.
at rx.Observable$30.onError(Observable.java:7252)
at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:127)
at rx.observers.SafeSubscriber.onError(SafeSubscriber.java:96)
at rx.internal.operators.OperatorMap$1.onError(OperatorMap.java:48)
at rx.internal.operators.OperatorMap$1.onNext(OperatorMap.java:56)
at rx.internal.operators.NotificationLite.accept(NotificationLite.java:150)
at rx.subjects.SubjectSubscriptionManager$SubjectObserver.emitNext(SubjectSubscriptionManager.java:254)
at rx.subjects.BehaviorSubject.onNext(BehaviorSubject.java:166)
at rx.Observable$34.onNext(Observable.java:7437)
at rx.observers.SafeSubscriber.onNext(SafeSubscriber.java:104)
at rx.internal.operators.OperatorMerge$InnerSubscriber.emit(OperatorMerge.java:610)
at rx.internal.operators.OperatorMerge$InnerSubscriber.onNext(OperatorMerge.java:536)
at rx.internal.operators.OperatorSingle$1.onCompleted(OperatorSingle.java:75)
at rx.internal.operators.OperatorTake$1.onNext(OperatorTake.java:72)
at rx.internal.operators.OperatorSubscribeOn$1$1$1.onNext(OperatorSubscribeOn.java:76)
at com.mycompany.servercall.ServerCall$1$1.call(ServerCall.java:56)
at com.mycompany.servercall.ServerCall$1$1.call(ServerCall.java:47)
at rx.Observable.unsafeSubscribe(Observable.java:7464)
at rx.internal.operators.OperatorSubscribeOn$1$1.call(OperatorSubscribeOn.java:62)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:45)
... 7 more
Caused by: java.lang.RuntimeException: Interrupted while waiting for subscription to complete.
at rx.observables.BlockingObservable.blockForSingle(BlockingObservable.java:474)
at rx.observables.BlockingObservable.single(BlockingObservable.java:348)
at com.mycompany.myapp.data.CachedThing.buildCachedThing(CachedThing.java:66)
at com.mycompany.myapp.data.CachedThing.<init>(CachedThing.java:28)
at com.mycompany.myapp.data.FilterFunc.call(FilterFunc.java:189)
at com.mycompany.myapp.data.FilterFunc.call(FilterFunc.java:175)
at com.mycompany.myapp.data.CachedThing.merge(CachedThing.java:60)
at com.mycompany.myapp.data.ResponseCache.update(ResponseCache.java:80)
at com.mycompany.myapp.data.TransformFunc.call(TransformFunc.java:105)
at com.mycompany.myapp.data.TransformFunc.call(TransformFunc.java:99)
at com.mycompany.servercall.CallState$3.map(CallState.java:79)
at com.mycompany.servercall.CallState$9.call(CallState.java:195)
at com.mycompany.servercall.CallState$9.call(CallState.java:193)
at rx.internal.operators.OperatorMap$1.onNext(OperatorMap.java:54)
... 22 more
Caused by: java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1279)
at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:202)
at rx.observables.BlockingObservable.blockForSingle(BlockingObservable.java:471)
... 35 more
Caused by: rx.exceptions.OnErrorThrowable$OnNextValue: OnError while emitting onNext value: .class
at rx.internal.operators.OperatorMap$1.onNext(OperatorMap.java:56)
... 22 more
CachedThing.buildCachedThing
has this block of code that I think is the culprit:
List<SubThing> subThings = Observable.from(things) //
.map(transformFunction) //
.filter(not(isNullFunction)) //
.distinct() //
.toList() //
.toBlocking() //
.single();
I tried writing a testcase to repro but couldn’t get it to fail. I’m guessing there’s something broken between the android runtime and rxjava’s thread management, but I couldn’t get any further than that.
Issue Analytics
- State:
- Created 9 years ago
- Comments:30 (20 by maintainers)
Top Results From Across the Web
Waiting for parallel RX subscribers to complete - Stack Overflow
I have to have the following code at the of the main() method to stop it exiting immediately. while (!subscription.isUnsubscribed()) { Thread.sleep(100); }....
Read more >io.reactivex.internal.util.BlockingHelper java code examples
currentThread().interrupt(); // using Runtime so it is not checked throw new IllegalStateException("Interrupted while waiting for subscription to complete.
Read more >Dataproc release notes - Google Cloud
Dataproc Serverless for Spark now now uses runtime version 1.0.22 and 2.0.2. ... storage quota after Batch is complete and until diagnostics is...
Read more >ChangeLog-5.0 - The Linux Kernel Archives
And there for a tx completion interrupt was not signaled. This fix corrects the problem by properly marking the end of a multi...
Read more >RxJava One Observable, Multiple Subscribers - Baeldung
The default behavior of multiple subscribers isn't always desirable. ... We subscribe and then wait for a second before connecting.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
A quick note about
Thread
interruptions on Android. AFAIK application process is killed in case of ANRs (either automatically or after a user confirmation). So ANRs do not lead to thread interruptions.However, there is a case when I use
toBlocking
and get an interruption: sync adapter thread.On Android we can create a component that will be plugged to the sync part of the framework. Basically Android framework spawns a new thread for you and invokes your code in that thread. Application sync is supposed to be finished when this thread finishes. In our sync adapter code we build a chain of observables that can perform some operations concurrently using other threads. So the sync adapter code invoked in the sync thread looks like
buildChainOfObservables().toBlocking().single();
. Sync can be canceled (e.g. by user request, unchecking a checkbox in system settings, or when it takes too long). And a default implementation of cancelation request is this sync thread interruption.@Alexander--
RxJava core libraries only interrupt when unsubscribing a scheduled action on a
Scheduler
that is still running. This is in turn just leveraging theFuture.cancel
semantics of Java. RxJava does not actually ever callThread.interrupt
.The async-utils are just utility methods on top of Schedulers so unless there is some effort to specifically prevent interrupt (nothing I can see while browsing the code) they will also be interrupted if they are still executing when unsubscribe is invoked.
If a Scheduler is not involved RxJava itself does nothing other than invoke
Subscription.unSubscribe
which flips a boolean and calls any registered callbacks. Thus, anObservable
implementation can choose to register aSubscription
that then interrupts and interruptible unit of work.I’m wondering if that is better for an Observable implementation (via
Observable.create
) to opt-in to interrupts rather than the currentScheduler
interrupt mechanism which seems like it could be surprising.