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

Fatal error - memory exhausted trying to edit a wp_template #7

Closed
bobbingwide opened this issue Oct 29, 2020 · 8 comments
Closed

Fatal error - memory exhausted trying to edit a wp_template #7

bobbingwide opened this issue Oct 29, 2020 · 8 comments
Assignees
Labels
bug Something isn't working

Comments

@bobbingwide
Copy link
Owner

bobbingwide commented Oct 29, 2020

Also note that sometimes editing the CPTs directly caused an out of memory problem due to an infinitely descending loop of action hooks the_content and pre_render_block.

I'm going to raise this as a separate issue to see if this is something I've done or a problem with Gutenberg itself.

Originally posted by @bobbingwide in #1 (comment)

Problem

  • Attempting to use Appearance > Templates to edit a specific template part can lead to a timeout / memory exhausted issue.

With oik-bwtrace activated I got

Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 585728 bytes) in C:\apache\htdocs\wordpress\wp-content\plugins\oik-bwtrace\includes\class-BW-trace-record.php on line 191

The trace log file was 364MB. The call stack at the end of the trace file was 3647 functions deep.

@bobbingwide
Copy link
Owner Author

bobbingwide commented Oct 29, 2020

Problem analysis

Trace file analysis

The current filter stack is getting deeper and deeper:

C:\apache\htdocs\wordpress\wp-content\plugins\gutenberg-wordpress-source\build\block-library\blocks\navigation.php(107:0)
gutenberg_render_block_core_navigation(5) 67 0 2020-10-29T10:21:55+00:00 0.256835 0.008822 cf=the_content,pre_render_block,the_content,pre_render_block,the_content,pre_render_block,pre_render_block 
13584 24 715 6291456/8388608 256M F=468 3 Array

...

C:\apache\htdocs\wordpress\wp-content\plugins\gutenberg-wordpress-source\build\block-library\blocks\navigation.php(107:0)
gutenberg_render_block_core_navigation(7) 69 0 2020-10-29T10:21:55+00:00 0.276341 0.009612
cf=the_content,pre_render_block,the_content,pre_render_block,the_content,pre_render_block,the_content,pre_render_block,the_content,pre_render_block,pre_render_block 
14048 24 715 8388608/8388608 256M F=468 3 Array

The repeated calls in the stack are where the template-part called footer-part ( postId=548 )is being processed

Data

template: single
URL: https://s.b/wp56/wp-admin/post.php?post=694&action=edit
The content of the wp_template in question was

<!-- wp:template-part {"postId":665,"slug":"header-2-columns","theme":""} /-->

<!-- wp:template-part {"postId":751,"slug":"post-content","theme":"custom"} /-->

<!-- wp:template-part {"postId":561,"slug":"footer","theme":"fizzie"} /-->

I tried to use phpMyAdmin to see the content of all the posts with post_type wp_template but it's reporting errors.

Aside:
There were 20 posts which were for 'index' with post_status 'auto-draft'.
I'd seen these a couple of times using Site Editor (beta) - I believe this is similar to a known problem reported for template parts. WordPress/gutenberg#26402

@bobbingwide bobbingwide changed the title Fatal error - memory exhausted trying to edit a wp_template_part Fatal error - memory exhausted trying to edit a wp_template Oct 29, 2020
@bobbingwide bobbingwide self-assigned this Oct 29, 2020
@bobbingwide bobbingwide added the bug Something isn't working label Oct 29, 2020
@bobbingwide
Copy link
Owner Author

footer-part ( postId=548) contains

<!-- wp:paragraph -->
<p>(C) Copyright Bobbing Wide 2020</p>
<!-- /wp:paragraph -->

<!-- wp:oik-block/wp {"v":"v","p":"p"} /-->

template_part post-content ( postId=751 ) contains

<!-- wp:group {"className":"post","backgroundColor":"background"} -->
<div class="wp-block-group post has-background-background-color has-background"><div class="wp-block-group__inner-container"><!-- wp:post-title /-->

<!-- wp:post-content /-->

<!-- wp:post-tags /-->

<!-- wp:post-hierarchical-terms {"term":"category"} /--></div></div>
<!-- /wp:group -->

The only post that refers to postId 548 is the singular wp_template.

<!-- wp:template-part {"postId":665,"slug":"header-2-columns","theme":""} /-->

<!-- wp:group {"style":{"color":{"background":"#b7cdd6"}}} -->
<div class="wp-block-group has-background" style="background-color:#b7cdd6"><div class="wp-block-group__inner-container"><!-- wp:post-title {"isLink":true} /-->

<!-- wp:post-content /-->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph --></div></div>
<!-- /wp:group -->

<!-- wp:template-part {"postId":548,"slug":"footer-part","theme":"fizzie"} /-->

I can't see why this is being processed.

@bobbingwide
Copy link
Owner Author

There is another post that references postId 548; it's 715 which is an autosaved revision of the single wp_template 694.

<!-- wp:template-part {"postId":665,"slug":"header-2-columns","theme":""} /-->

<!-- wp:post-title /-->

<!-- wp:post-content /-->

<!-- wp:template-part {"postId":548,"slug":"footer-part","theme":"fizzie"} /-->

This is being processed in WP_Rest_Revisions_Controller->prepare_item_for_response()

When I remove the wp:post-content block the processing completes.
It would appear that wp:post-content is being expanded recursively.
When trace is enabled we run out of memory, otherwise we run out of time.

@bobbingwide
Copy link
Owner Author

In packages/block-library/src/post-content/edit.js there's a comment that says
"Only render InnerBlocks if the context is different from the active post to avoid infinite recursion of post content."

The code tests:

	if (
		contextPostId &&
		contextPostType &&
		contextPostId !== currentPostId &&
		contextPostType !== currentPostType

We probably need something in the server to do the same thing.

@bobbingwide
Copy link
Owner Author

bobbingwide commented Oct 30, 2020

So far I've found a couple of ways to stop the infinite recursion.

In WP_Rest_Revisions_Controller->prepare_item_for_response() don't invoke the_content filter to produce a rendered version of the post's content. Just assign the $post->post_content.

This was a core hack, so I looked for an alternative solution to implement the fix in Gutenberg.

In gutenberg_render_block_with_assigned_block_context() I added a test to see if the post_type of the global $post is a 'revision'. If it is then we return early, pre-rendering an empty string.

This avoids calling $block->render() at the end of the function.

This fix doesn't seem to adversely affect the Revisions dialog.

I also noted that in WP_Rest_Revisions_Controller->prepare_item_for_response() the value of $GLOBAL['post'] is set to the $post parameter but isn't reset. Is this relevant?

@bobbingwide
Copy link
Owner Author

bobbingwide commented Oct 30, 2020

Looking at the logic to render the post-content block in gutenberg_render_block_core_post_content, I can see that it returns early when the block context postId is not set.
I added logic to return early when the context postType was revision.

if ( 'revision' === $block->context['postType'] ) {
		return '';
	}

This worked too. It didn't seem necessary to run isset as both 'postId' and 'postType' are set at the same time in gutenberg_render_block_with_assigned_block_context() - which is the function I'd changed earlier.

I think it makes more sense to fix the block that's failing rather than the calling routine.

@bobbingwide
Copy link
Owner Author

Having developed a local fix and an issue against Gutenberg I could consider closing this. But I'm not going to until it's actually been fixed in Gutenberg. Meanwhile, since I've not implemented it in a committed branch, I'll have to reapply my fix for each new version of Gutenberg.

@bobbingwide
Copy link
Owner Author

I haven't suffered a recursion problem for a while. This is probably due to not testing for it. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant