ReactiveX / RxJavaString

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Android app freezes after upgrading rxandroid 0.24 -> 0.25

zella opened this issue · comments

I used io.reactivex:rxandroid:0.24.0 and io.reactivex:rxjava-string:0.22.0

After ugrade dependency to io.reactivex:rxandroid:0.25.0, app became freezes on

public static String joinedBy(List<String> src, String separator) {
       return StringObservable.join(Observable.from(src), separator).toBlocking().single();
}
commented

rxjava-string:1.0.0 is same.
And this problem issue in normal java environment too.

My test logic

        Observable<String> columns = Observable.from("a,b,c,d".split(","))
            .map(i -> String.format("%s.%s", "prefix", i));
        Observable<String> query = StringObservable.join(columns, ",");

        System.out.println(query.toBlocking().single());

io.reactivex:rxjava:1.0.8 + io.reactivex:rxjava-string:* , is working.
io.reactivex:rxjava:1.0.9~ + io.reactivex:rxjava-string:* is not working.

So I guess some blocking logic changed in rxjava 1.0.12.

I found some specific two check points.

point 1. in BlockingObservable#blockForSingle

...
    private T blockForSingle(final Observable<? extends T> observable) {
        final AtomicReference<T> returnItem = new AtomicReference<T>();
        final AtomicReference<Throwable> returnException = new AtomicReference<Throwable>();
        final CountDownLatch latch = new CountDownLatch(1);

        Subscription subscription = observable.subscribe(new Subscriber<T>() {
            @Override
            public void onCompleted() {
                latch.countDown();  // Runtime doesn't reach this line. So  CountDownLatch continue on 1 state.
            }

            @Override
            public void onError(final Throwable e) {
                returnException.set(e);
                latch.countDown();
            }

            @Override
            public void onNext(final T item) {
                returnItem.set(item);
            }
        });

        try {
            latch.await();  // So deadlock situation. 
        } catch (InterruptedException e) {
            subscription.unsubscribe();
            Thread.currentThread().interrupt();
            throw new RuntimeException("Interrupted while waiting for subscription to complete.", e);
        }
...

point 2. StringObservable#join

    public static Observable<String> join(final Observable<String> source, final CharSequence separator) {
        return source.lift(new Operator<String, String>() {
            @Override
            public Subscriber<String> call(final Subscriber<? super String> o) {
                return new Subscriber<String>(o) {
                    boolean mayAddSeparator;
                    StringBuilder b = new StringBuilder();

                    @Override
                    public void onCompleted() {
                        String str = b.toString();
                        b = null;
                        if (!o.isUnsubscribed())
                            o.onNext(str);
                        if (!o.isUnsubscribed())  // This code is true after unsubscribed. So problem in point 1 issue. 
                            o.onCompleted();
                    }

I don't understand why. I describe just situation.

@davidmoten the bug is in join not requesting max but just the amount the child does. Simplest fix is to add an onStart.

Thanks for the report @zella, @neocoin and analysis @akarnokd. I'll have a look.

I think a fix has been merged in #24. I'll attempt to get it released.