smarty icon indicating copy to clipboard operation
smarty copied to clipboard

Smarty_Internal_Template::render(): Cannot use output buffering in output buffering display handlers

Open Chrissyx opened this issue 1 year ago • 1 comments

Not sure if this is a Smarty issue or some bad server configuration or something like that. While running my application with Smarty 4.5.2 on PHP 8.2, no errors or whatsoever appear. Everything renders fine. However, the Apache web server log gets flooded with errors like this:

PHP Fatal error: Smarty_Internal_Template::render(): Cannot use output buffering in output buffering display handlers in vendor/smarty/smarty/libs/sysplugins/smarty_internal_template.php on line 234

Any idea what's going on here?

Chrissyx avatar May 10 '24 20:05 Chrissyx

Without a reproduction scenario it's hard to say. Have you searched for the error online? Maybe this helps: https://stackoverflow.com/questions/33936067/cannot-use-output-buffering-in-output-buffering-display-handlers#34164495

This might suggest that you are calling Smarty from an ob_start callback. But I don't know if that is accurate of course.

wisskid avatar May 13 '24 22:05 wisskid

I'm not using such a callback. To solve this issue I've had removed my only ob_start('ob_gzhandler'); call and currently using no output buffering at all. The result was the error logged above. Could perhaps a misconfigured php.ini relate to that?

Chrissyx avatar May 16 '24 17:05 Chrissyx

@Chrissyx I've tried to reproduce this, but I can't. Can you show a (preferably minimal) example that triggers this error?

wisskid avatar May 16 '24 20:05 wisskid

After spending five more hours into researching the issue, I think I finally found it. It happens by displaying a fairly large website with a lot of HTML data. Locally on my machine I got a blank page and this error logged by system:

PHP Fatal error: PHP Request Shutdown: Cannot use output buffering in output buffering display handlers in Unknown on line 0

However by using the debugger on the same view it crashed due to this:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 49690624 bytes) in vendor\smarty\smarty\libs\sysplugins\smarty_internal_template.php on line 234

Note that providing and assigning the data to render is no problem at all. It actually fails by printing out the surrounding tags as stated in the TPL file, e.g. as list entries with images and links. Not sure if Smarty can handle it better, but the initial error was definitely misleading.

Chrissyx avatar May 17 '24 21:05 Chrissyx

That must be a SERIOUSLY complex template if 128MB of RAM isn't enough to render it. Does the problem go away if you bump the PHP limit up to 256MB?

scottchiefbaker avatar May 17 '24 21:05 scottchiefbaker

Yes, it solves the problem and the page renders with no errors in the log. The template is not complex at all, it's just a long list with ~120k entries. I saved the page and it resulted in a 31 MB downloaded HTML file. So yeah, that might explain something.

Chrissyx avatar May 19 '24 10:05 Chrissyx

That sounds about right. At line 234, Smarty retrieves the template output from its internal buffer and writes it to output. If you have your own gzipping output buffer active however, PHP will need to allocate enough space to store the output in memory. From you error message, this is 49690624 bytes or approximately 47 MB which approximately matches your resulting 31 MB downloaded file.

Since the application has already used a bunch of memory for loading the data, the templates and passing the data to the templates, this in turn results in a memory overflow.

One could imagine a more efficient method of rendering the data in smaller batches and eliminating output buffers where possible, but for this use case an increasing the memory limit seems the easiest fix.

wisskid avatar May 20 '24 08:05 wisskid