Hi, I had a WSOD when rendering a composite layout. After some searches, I finally found a non evident infinite loop that PHP did not detected itself.
When rendering a view's block inside a composite layout, with the node row plugin configured with "Full node" module, if the current node being displayed is in the view's results, then it will try to render again composite inside, then views, then composite, then views...
I did a simple patch to detect and break this kind of recursion, it may needs some rewrite, but it works fine on my env.
Comments
Comment #1
pounardPatch is not easy to read, but you can apply it and compare with your own eyes the 2 files, you'll see I just added about 10 lines of code and re-indent 30 others (no big deal).
Comment #2
bengtan commentedHi,
Actually, there is already some recursion detection logic, but it only applied to nodes displayed via the Nodes and Zones tabs. However, I can see now that the recursion detection logic needs to be applied at a more general level.
So instead of using your patch, I have created a new patch that moves the logic upwards. It's not quite the same as your method, but hopefully it's just as good and the differences are negligible.
Please give this a try and see if it solves your issue.
Comment #3
pounardWhen I look at you patch I see that your method is almost the same, instead of using a global variable you use a static variable inside a function; but your algorithm remains the same.
I did not tested it yet, but I already have a note about it, you should not display the error message. In my case, this is not an error because the embedded view display the node with a different build mode that the full display, which help me placing node elements in the composite layout which are not displayed in the full page (so, by placing a block which displays a view which displays my own node is really what I want in this use case, this is not accidental).
I think maybe display the error message only if the user is site admin or if a site wide variable tells is set may be a bit less intrusive. Whatever is you choose, the message should never display to anonymous users (there is always the site wide setting that allow administrator to fully deactivate error messages for anonymous, but I don't think in this case your error message will be dropped).
I'll test it within the day.
Comment #4
bengtan commented> but your algorithm remains the same.
There is at least one small change ... my patch doesn't 'clear' the flag after the node has been rendered.
> you should not display the error message.
Hmmm ... in my opinion, it is actually an error because if Composite Layout were to obey the user, they would get an infinite loop. If Composite Layout cannot do what the user asks, it should inform the user so the user can fix their content or content structure. I think failing silently (ie. not emitting an error message) is a bad idea.
> display the node with a different build mode
Composite Layout only operates if the node is being viewed in 'full mode'. For any other build mode, Composite Layout won't do anything ... and the node won't be entered into the 'recursion list'.
Comment #5
pounardIn my case, the "Full node" is a build mode I want to be displayable inside my composite layout, I known that's weird, but it has a sense in this site.
True, and you should, because the content could be displayed more than one time in full mode on screen, it can be dumb to do that, but a site admin might want it (views can display nodes in full mode, blocks, the node page, and it can make sense).
EDIT:
Noting more logical than this, I agree, but in fact, I would do avoid recursions silently. In all cases, a non-owner for this node must not see the error message, in fact, any "normal" user should never see any of this kind of error message.
Comment #6
bengtan commentedHi,
> True, and you should,
If we're going to track the completion of node rendering, then we need to use reference counting instead of boolean flags.
> because the content could be displayed more than one time in full mode
> on screen, it can be dumb to do that, but a site admin might want it
Yes, although I was hoping this would be rare enough that I could just ignore it :)
> In all cases, a non-owner for this node must not see the error message,
Let's just pretend that we should show the error message only for certain types of users ... how would you decide this? Show the error only for users with certain permissions ie. 'administer nodes'? show the error only for users with edit access to the node?
If node A includes node B, and node B also includes node A, then show the error only for users who 'own' node A, or only for users who 'own' node B, or both?
Comment #7
pounardThe check should be the same than the menu system one:
Comment #8
bengtan commented> The check should be the same than the menu system one:
Hmmm ... okay. I'm okay with using this as the check.
Comment #9
pounardPlease test this patch, pretty much the same as yours, except I added a reset parameter for the recursion check function, in order for the recursion part to unmark the node as being rendered at the end of recursion loop to ensure that if the same node is rendered twice on the same page, it will be.
EDIT: Works fine @home.
EDIT: It made me change the _composite_nodes_recursion_check() function signature by adding parameters, but hopefully I kept the backward compat so if this function was used elsewhere it'll continue to work as expected.
Comment #10
bengtan commentedHi,
Committed. See http://drupal.org/cvs?commit=365006.
Thanks!
Comment #11
pounardNp, pleased I could help:)