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

Fix logic bug in poll promise/signal sync. #6192

Merged
merged 1 commit into from Apr 12, 2019

Conversation

@afshin
Copy link
Member

@afshin afshin commented Apr 12, 2019

Fixes incorrectly cached pending in async function (Poll#schedule()).

If a Poll is instantiated and its public methods are immediately invoked by a client without waiting for the first tick, one promise was accidentally skipped. This fixes that.

@jupyterlab-dev-mode
Copy link

@jupyterlab-dev-mode jupyterlab-dev-mode bot commented Apr 12, 2019

Thanks for making a pull request to JupyterLab!

To try out this branch on binder, follow this link: Binder

@@ -236,7 +236,9 @@ describe('Poll', () => {
expect(ticker.join(' ')).to.equal(tocker.join(' '));
poll.tick.then(tock).catch(() => undefined);
};
await poll.tick.then(tock);
Copy link
Member Author

@afshin afshin Apr 12, 2019

This was a kludge that made the test pass. This version will still pass.

@@ -236,7 +236,9 @@ describe('Poll', () => {
expect(ticker.join(' ')).to.equal(tocker.join(' '));
poll.tick.then(tock).catch(() => undefined);
};
await poll.tick.then(tock);
// Kick off the promise listener, but void its settlement to verify that
Copy link
Member Author

@afshin afshin Apr 12, 2019

This version of the test will only pass with this fix, so the comment about voiding the promise instead of awaiting it indicates that this is by design.

@afshin afshin added this to the 1.0 milestone Apr 12, 2019
// The `when` promise in the constructor options acts as a gate.
if (this.state.phase === 'constructed') {
if (next.phase !== 'when-rejected' && next.phase !== 'when-resolved') {
await pending.promise;
await this.tick;
Copy link
Contributor

@jasongrout jasongrout Apr 12, 2019

This part is equivalent to the old code, right? this.tick is this._tick.promise.

Copy link
Member Author

@afshin afshin Apr 12, 2019

This part is equivalent, yes.

@jasongrout
Copy link
Contributor

@jasongrout jasongrout commented Apr 12, 2019

It seems that the code change is strictly equivalent to what was there before. It seems that the fix that needs to be done is setting this._tick in the constructor to something that waits for the when promise. What do you think?

@afshin
Copy link
Member Author

@afshin afshin commented Apr 12, 2019

The problem addressed by this fix is effectively that the part of the code after the await is in a .then() and the poll state may have changed, but the const pending variable was still being referenced as though it was current.

const foo = this.tick;
await Promise.resolve();
// This is no longer guaranteed because the context may have changed.
console.log(foo === this.tick);

@@ -380,6 +378,7 @@ export class Poll<T = any, U = any> implements IDisposable, IPoll<T, U> {

// Update poll state.
const last = this.state;
const pending = this._tick;
Copy link
Contributor

@jasongrout jasongrout Apr 12, 2019

Ah, from conversation in gitter, I'm understanding now that the await above may make pending stale, but here we need pending to be the current this._tick. Is that the fix?

Copy link
Member Author

@afshin afshin Apr 12, 2019

Yes, exactly that.

@jasongrout
Copy link
Contributor

@jasongrout jasongrout commented Apr 12, 2019

Okay, thanks, I think I understand the change you made here.

And I think I understand where I went wrong too in my point. When we are in the constructed state, the only states that are allowed to schedule (and thus resolve the initial promise delegate) are the when-resolved or when-rejected states, so all other schedules pile up until after those are done, and the last schedule then wins the timeout race

@jasongrout jasongrout merged commit c0d1066 into jupyterlab:master Apr 12, 2019
9 checks passed
@jasongrout jasongrout removed this from the 1.0 milestone May 29, 2019
@jasongrout jasongrout added this to the 1.0 milestone May 29, 2019
@lock
Copy link

@lock lock bot commented Aug 6, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related discussion.

@lock lock bot locked as resolved and limited conversation to collaborators Aug 6, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

2 participants