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

Fixes NPEs reported in ReactiveX#1702 by synchronizing queue. #2471

Merged
merged 7 commits into from
Jan 23, 2015
Merged

Fixes NPEs reported in ReactiveX#1702 by synchronizing queue. #2471

merged 7 commits into from
Jan 23, 2015

Conversation

jnlopar
Copy link
Contributor

@jnlopar jnlopar commented Jan 20, 2015

Also adds a unit test for regression.

It appears there is a potential race condition if something adds to/removes from the PQ while it's inside the 'poll' operation, which is where the exceptions in #1702 seem to have actually come from. Therefore, the initial null check didn't really address the original problem. The test here seems to reliably recreate those conditions.

I considered using a PriorityBlockingQueue instead of synchronized, but since the isEmpty and poll calls should not allow something to interleave between them and access the queue, a synchronized block seemed wiser here.

synchronized (queue) {
if (!queue.isEmpty()) {
TimedAction polled = queue.poll();
polled.action.call();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not call the action while holding the lock. Just do a synchronized poll and call the action if you got a non-null value.

In addition, I think the COUNTER_UPDATER and counter can be moved into the worker itself because it can ensure total order locally and we can avoid a global serialization point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. I fixed the wrapping. Now I'm just using poll instead of isEmpty, since poll returns null iff isEmpty.

@akarnokd
Copy link
Member

Almost good. Two things:

  • Since we only use offer/poll, you can use the unbounded PriorityBlockingQueue now
  • Could you move counter and COUNTER_UPDATER into the InnerCurrentThreadScheduler class, both non-static fields?

@akarnokd akarnokd added the Bug label Jan 21, 2015
@akarnokd
Copy link
Member

We are using AtomicFieldUpdaters to save on the instance cost of AtomicIntegers. Could you change the counter to use AtomicLongFieldUpdater?

@jnlopar
Copy link
Contributor Author

jnlopar commented Jan 23, 2015

Done. On a related but side-note, do you know if these field updaters are proguard-safe for obfuscation? They reflect on field name for sure. It might be worth looking into. The fix would probably be implementing the abstract setters and getters, which would obviously be a bit more boilerplate and kinda less fun, but might be worth it if it reduces custom proguard rules required to use rx.

@akarnokd
Copy link
Member

Thanks for the changes, looks good to me. I don't know about ProGuard.

akarnokd added a commit that referenced this pull request Jan 23, 2015
Fixes NPEs reported in #1702 by synchronizing queue.
@akarnokd akarnokd merged commit 4fbf11a into ReactiveX:1.x Jan 23, 2015
@jnlopar
Copy link
Contributor Author

jnlopar commented Jan 23, 2015

Looks like per the proguard manual, it does indeed recognize FieldUpdater declarations, so this should be fine.

@JakeWharton
Copy link
Contributor

Wow I did not expect that. How uncharacteristically useful of them! Good to know for the future.

@jnlopar
Copy link
Contributor Author

jnlopar commented Jan 23, 2015

http://proguard.sourceforge.net/manual/introduction.html

See the 'Reflection' section (no anchor link). That lists the basic reflection methods it automatically detects.

@jnlopar jnlopar deleted the fix1702 branch January 23, 2015 19:20
@benjchristensen benjchristensen mentioned this pull request Feb 3, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants