Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug in OnSubscribeFromIterable unsubscribed child logic #3006

Closed
andres-pipicello opened this issue Jun 4, 2015 · 5 comments
Closed

Bug in OnSubscribeFromIterable unsubscribed child logic #3006

andres-pipicello opened this issue Jun 4, 2015 · 5 comments

Comments

@andres-pipicello
Copy link

Hello

The code is missing an additional check for child unsubscription after calling the iterator next method. This is needed when using in conjunction with operators like take, that unsubscribes itself in the onNext method.

Regards

@davidmoten
Copy link
Collaborator

Sorry, can't see the issue with take, can you elaborate? If the child has unsubscribed during the onNext then the next loop will check for unsubscription and exit.

The iterator next method could take enough time for unsubscription to have happened in the meantime so we could insert another check for unsubscription before emitting. I'll see what the others think of this as I imagine it would compromise performance a bit for common use cases like using java Collections as sources because each emission would require two volatile reads of unsubscribed.

if (o.isUnsubscribed())
    return;
T val = it.next();
if (o.isUnsubscribed()) 
    return;
o.onNext(val);

Is this what you were meaning?

@andres-pipicello
Copy link
Author

The problem arised when using an Iterable which produces iterators with a blocking hasNext.
Imagine the case where the hasNext call would block after retrieving 10 elements (so, in the eleventh call). Chaining a take/limit of 10 would still block, even after emiting 10 elements.

We did a quick patch:

while (it.hasNext() && --numToEmit >= 0) {
                            if (o.isUnsubscribed()) {
                                return;
                            }
                            o.onNext(it.next());
                            if (o.isUnsubscribed()) {
                                return;
                            }

                        }

@zsxwing
Copy link
Member

zsxwing commented Jun 5, 2015

How about checking isUnsubscribed before hasNext, such as:

                        while (!o.isUnsubscribed() && it.hasNext() && --numToEmit >= 0) {
                            o.onNext(it.next());
                        }
                        if (o.isUnsubscribed()) {
                            return;
                        }

@davidmoten
Copy link
Collaborator

@pelecomepibe yep that does look something to avoid
@zsxwing LGTM

akarnokd added a commit that referenced this issue Jun 9, 2015
Observable.from(iterable) - ensure it.hasNext() is not called unnecessarily #3006
@akarnokd
Copy link
Member

Thanks for reporting. Fix released in 1.0.12.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants