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.

"Interrupted while waiting for subscription to complete." in 1.0.0-rc8

See original GitHub issue

Doesn’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:closed
  • Created 9 years ago
  • Comments:30 (20 by maintainers)

github_iconTop GitHub Comments

1reaction
roman-mazurcommented, Nov 7, 2014

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.

0reactions
benjchristensencommented, Nov 8, 2014

@Alexander--

Or is it some internal mechanic for disposing of Schedulers only?

RxJava core libraries only interrupt when unsubscribing a scheduled action on a Scheduler that is still running. This is in turn just leveraging the Future.cancel semantics of Java. RxJava does not actually ever call Thread.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.

unsubscribing from Observale (in currently released version), during interruptable operation will interrupt it?

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, an Observable implementation can choose to register a Subscription 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 current Scheduler interrupt mechanism which seems like it could be surprising.

Read more comments on GitHub >

github_iconTop 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 >

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