• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

Fixed Output buffering clearing causes notice error

AlexT

Well-known member
#1
Got this notice error in my log files (XF 1.2 beta 3):
Code:
Application.php(186)    ob_end_clean(): failed to delete buffer. No buffer to delete    E_NOTICE
PHP:
// see http://bugs.php.net/bug.php?id=36514
if (!@ini_get('output_handler')) while (@ob_end_clean());
It is caused by calling ob_end_clean() even if there is not a buffer.

Not sure if this workaround fix is still needed for older PHP versions, but if it is, perhaps it could be enhanced with this line of code:
PHP:
if (!@ini_get('output_handler')) while (ob_get_level() > 0) { ob_end_clean(); };
This will clean output buffering if and only if it's already started.
 
Last edited:

AlexT

Well-known member
#2
Forgot to mention, this test server runs:

PHP 5.3.26 with output_buffering set to Off. Gzip is enabled by the web server (Nginx).
 

AlexT

Well-known member
#4
That's generally the reason we use the shut up operator there. I'm not sure why that should be logged...
Mike, I am using a debugger that shows all errors even with the dog-slow @ prefix . With the suggested fix I believe it should not be necessary to suppress the error anymore and still achieve what you wanted to.
 

AlexT

Well-known member
#5
I found this remark in the Mediawiki SVN:
// There's another bug in ob_gzhandler (see also the comment at
// the top of this function) that causes it to gzip even empty
// responses, meaning it's impossible to produce a truly empty
// response (because the gzip header is always there). This is
// a problem because 304 responses have to be completely empty
// per the HTTP spec, and Firefox behaves buggily when they're not.
// See also http://bugs.php.net/bug.php?id=51579
// To work around this, we tear down all output buffering before
// sending the 304.
// On some setups, ob_get_level() doesn't seem to go down to zero
// no matter how often we call ob_get_clean(), so instead of doing
// the more intuitive while ( ob_get_level() > 0 ) ob_get_clean();
// we have to be safe here and avoid an infinite loop.
// Caching the level is not an option, need to allow it to
// shorten the loop on-the-fly (bug 46836)
So perhaps above suggested code should be changed to:

PHP:
if (!@ini_get('output_handler'))
{
    for ($i = 0; $i < ob_get_level(); $i++)
    {
      ob_end_clean();
    }
}
 

Mike

XenForo developer
Staff member
#7
Yeah, I think that code is bugged. If it's deep within an output buffer, I don't think it cleans it properly. I'm looking at an alternative approach that doesn't use the shut up operator.
 

Mike

XenForo developer
Staff member
#8
Trying:
Code:
            $level = ob_get_level();
            while ($level)
            {
                ob_end_clean();
                $newLevel = ob_get_level();
                if ($newLevel >= $level)
                {
                    break;
                }
                $level = $newLevel;
            }
As that should handle any infinite loop possibility (by the get level not changing correctly).