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

ob_end_flush(): failed to delete and flush buffer. No buffer to delete or flush #214

Closed
adrianbj opened this issue Aug 3, 2016 · 14 comments

Comments

@adrianbj
Copy link
Contributor

adrianbj commented Aug 3, 2016

I get this error when PHP's output_buffering is set to 0, which seems to be quite common on shared hosts.

I think it is likely related to this: http://php.net/manual/en/function.ob-get-level.php#109001 and the fact that ob_get_level returns one at the beginning of the script.

The error comes from this line: https://github.com/nette/tracy/blob/master/src/Tracy/Debugger.php#L436

Let me know if you have any trouble reproducing - it may only be occurring because I am manually calling Debugger::shutdownHandler() from another script.

@dg
Copy link
Member

dg commented Aug 9, 2016

There is @, so it should not produce rror.

@adrianbj
Copy link
Contributor Author

Sorry for the delay in replying - I was on vacation last week.

It doesn't produce the error with the @, but the problem is that it still results in a blank page being returned. I can fix it by replacing:

while (ob_get_level() > self::$obLevel) {

with

while (ob_get_level() > 1) {

here: https://github.com/nette/tracy/blob/master/src/Tracy/Debugger.php#L430

I am not sure if that is the correct/appropriate solution, but it is the only way I can seem to prevent a blank screen from being returned in certain situations.

Is there any other info I can provide?

@dg
Copy link
Member

dg commented Aug 16, 2016

Can you describe in which situations is returned blank screen? Because setting output_buffering = 0 is fine.

@adrianbj
Copy link
Contributor Author

Ok, I have tracked it down (I think), although it may be a little tricky for you to replicate. The problem only occurs when I manually call Debugger::shutdownHandler() which I have do for a specific situation - can explain more if you want. Now the other thing required to cause the blank screen is to do a header location redirect and call exit on the line after the header call. If I remove that exit, then it works fine.

Does that give you enough insight to work from? If not, let me know and I'll set up a site so you can test.

Thanks!

@adrianbj
Copy link
Contributor Author

@dg - would you consider adding:

if(!ob_get_level()) ob_start();

just before this line:

self::$obLevel = ob_get_level();

This is in line with what is suggested here: http://php.net/manual/en/function.ob-get-level.php#109001

It seems to fix everything at my end. Can you see any possible side-effects?

@dg
Copy link
Member

dg commented Dec 27, 2016

ob_start() is not good idea, because it blocks server output until connection is closed.

Simply, I don't understand where is problem, so I am unable to solve it.

@adrianbj
Copy link
Contributor Author

ob_start() is not good idea, because it blocks server output until connection is closed.

Good point!

OK, I'll try to explain in more detail. It all relates back to this issue: #185

In my last comment you'll see that I am now calling Debugger::shutdownHandler() before my script shuts down so I can get the AJAX bar to work. Without that, the AJAX bar doesn't show. The side-effect of calling Debugger::shutdownHandler() however is the problem described in the issue where I get a blank page because of the Debugger::removeOutputBuffers method.

Maybe manually calling Debugger::shutdownHandler() messes with the integrity of self::$obLevel?

I do know that if I add 1 to the value of self::$obLevel then everything works just fine.

@dg
Copy link
Member

dg commented Dec 27, 2016

shutdownHandler() should flush all buffers created after Tracy is enabled. So ob_get_level() should return the same value before Tracy\Debugger::enable(), after enable(), before shutdownHandler() (*) and after shutdownHandler(). Can you check it?

*) before shutdownHandler() it can be greater, but after that and when you call shutdownHandler() two times, value should be the same as before enable().

@adrianbj
Copy link
Contributor Author

I am getting:

before enable: 0
after enable: 0
before shutdown: 1
after shutdown: 0

@dg
Copy link
Member

dg commented Dec 27, 2016

It seems ok. Can you dump ob_get_status(TRUE) before manual shutdown?

@adrianbj
Copy link
Contributor Author

    [0] => Array
        (
            [name] => default output handler
            [type] => 0
            [flags] => 112
            [level] => 0
            [chunk_size] => 0
            [buffer_size] => 16384
            [buffer_used] => 0
        )

@dg
Copy link
Member

dg commented Dec 27, 2016

So after enable() you code starts an output buffer, shutdownHandler() flushes and closes it (via ob_end_flush()).

This should not produce ob_end_flush(): failed to delete and flush buffer, because buffer existed and was closed.

At the same time, it should not result in a blank page, because it is flushed.

So I'm stuck :-)

For what purpose do you use the buffer? Page cache?

You can try to render Bar this way instead of calling shutdownHandler:

Debugger::getBar()->render();
Debugger::$showBar = FALSE;

@adrianbj
Copy link
Contributor Author

For what purpose do you use the buffer? Page cache?

I believe the issue is starting here: https://github.com/processwire/processwire/blob/50f2834a0ae2a9f9f2ac53439184ebdc04db2f54/wire/core/admin.php#L89

Removing that ob_start() does fix things, but it also seems like your solution of:

Debugger::getBar()->render();
Debugger::$showBar = FALSE;

instead of calling the shutdown handler also works, so thank you very much for that!

Just an FYI - as I think I mentioned in that other issue, all of this is only problem when using that SessionHandlerDB module: https://github.com/processwire/processwire/blob/50f2834a0ae2a9f9f2ac53439184ebdc04db2f54/wire/modules/Session/SessionHandlerDB/SessionHandlerDB.module

@adrianbj
Copy link
Contributor Author

Sorry to bring this up again @dg - maybe I should have started a new issue, but since it only seems to affect me, I thought it better to add here. I just noticed that even though:

Debugger::getBar()->render();
Debugger::$showBar = FALSE;

gets the AJAX bar working, it doesn't get the Redirect working. Again this is only an issue with that SessionHandlerDB module.

It might be good to note that I am having to add:

if(ob_get_level() == 0) ob_start();

before those two lines, otherwise php header redirects don't work at all unless php.ini has output_buffering on by default.

Any thoughts on what might be preventing the Redirect bar from working?

Here is what a dump of $_SESSION['_tracy'] looks like:

with SessionHandlerDB off:
screen shot 2017-02-13 at 11 54 29 am

and with it on:
screen shot 2017-02-13 at 11 53 50 am

These are on exactly the same page after the same redirect. I don't know why the redirect index is NULL and the bar index has three items.

I don't want to take up anymore of your time on this, but if you have any quick ideas of why it might be happening, that would be greatly appreciated.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants