Skip to content

Fixed bug #78434 #5344

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

Closed
wants to merge 2 commits into from
Closed

Fixed bug #78434 #5344

wants to merge 2 commits into from

Conversation

nikic
Copy link
Member

@nikic nikic commented Apr 3, 2020

Fix for https://bugs.php.net/bug.php?id=78434. Set the ZEND_GENERATOR_DO_INIT flag whenever we perform a yield from, not when while performing "ensure initialized".

The intention here is that we should take the current() value of the generator before we advance it, unless the generator is before first yield, in which case we do need to advance it.

I'm not really sure if the implementation is right, or even if the semantics are right... Especially not sure if the change in Zend/tests/generators/gc_with_root_parent_mismatch.phpt makes sense.

@nikic
Copy link
Member Author

nikic commented Apr 3, 2020

@bwoebi What do you think about this?

yield from $generator;

$generator = $function();
// Comment out this line to get the correct result.
Copy link

Choose a reason for hiding this comment

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

Suggested change
// Comment out this line to get the correct result.

@@ -0,0 +1,28 @@
--TEST--
Bug #78434: Generator yields no items after valid() call
Copy link

Choose a reason for hiding this comment

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

I was a bit wrong in the bug description. The generator just skips the first item. See https://3v4l.org/2HBSX

Suggested change
Bug #78434: Generator yields no items after valid() call
Bug #78434: Generator skips first item after valid() call

@bwoebi
Copy link
Member

bwoebi commented Apr 3, 2020

Well, the intended semantics of yield from is that it does only advance the inner generator if next() is explicitly called. Otherwise it shall do nothing except priming the passed generator if it is not primed yet.
From that perspective the test result change looks wrong.

i.e. if a same generator is yielded from different sources, they must always reflect the current iteration point of the generator and only next() shall be able to advance the generator.

return;
if (UNEXPECTED(orig_generator->flags & ZEND_GENERATOR_DO_INIT)) {
orig_generator->flags &= ~ZEND_GENERATOR_DO_INIT;
if (!Z_ISUNDEF(generator->value)) {
Copy link
Member

@bwoebi bwoebi Apr 3, 2020

Choose a reason for hiding this comment

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

This check is bogus … because the direct yielded generator might not be primed yet (i.e. not have a value), but the inner generator (i.e. see the test) may.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't get what you mean. The value is only stored on the inner generator. This check matches what was there before as well.

@bwoebi
Copy link
Member

bwoebi commented Apr 3, 2020

Essentially your new proposed semantics are: advance the yield from'ed generator once unless it has not been primed yet, then prime it. Sounds weird to me.

@nikic
Copy link
Member Author

nikic commented Apr 3, 2020

Essentially your new proposed semantics are: advance the yield from'ed generator once unless it has not been primed yet, then prime it. Sounds weird to me.

That's not the intention. This is supposed to work as you described in your previous comment (which does not match the current behavior).

I've now pushed another commit to restore the behavior on gc_with_root_parent_mismatch.phpt by unsetting the DO_INIT flag only after the resume finishes. I suspect this is still not right though...

@bwoebi
Copy link
Member

bwoebi commented Apr 3, 2020

I can't spot anything inherently wrong with this now. To be sure maybe run it once against a generator intensive test-suite like in amp once?

@nikic
Copy link
Member Author

nikic commented Apr 9, 2020

@bwoebi Ran this against amp/http-client/http-server, no issues. As this is still a change in behavior that may have unexpected consequences, I'm only going to apply this to 7.4 though.

@nikic
Copy link
Member Author

nikic commented Apr 9, 2020

Merged as 823a956 into 7.4 upwards.

@nikic nikic closed this Apr 9, 2020
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.

4 participants