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
Quick-Cache only works iff the output buffer contains the entire page #97
Comments
@wmark Thank you very much for the bug report. I'm aware that Quick Cache is not compatible with Your suggestion to add checks "to determine in which phase the callback has been called" would pose, as you mentioned, other problems related to buggy differences in PHP versions with As output buffering is a core part of what Quick Cache does, I'm not sure it makes sense to introduce such potentially buggy behavior into the plugin. I do wish there was a reliable way to make Quick Cache work nicely alongside other plugins that register callbacks with I'll leave this issue open for now and put some more thought into how I might be able to make this work. I'd also like to get @JasWSInc's thoughts. |
@wmark Thanks for the report! Output buffers are stackable, so when one is opened and then the buffer is closed, the output callback for the last open handler is called upon; and this does not impact others farther up the chain. Generally speaking, it's a good practice not to call I do know what you mean about time-to-first-byte though. I have often used That said, I'm glad that you posted this issue. I think it's a good idea for us to look at some ways that we can guard against this. I was not aware of it until just now, but it looks like PHP v5.4+ now supports some new options in the third
As you point out, |
@raamdev This test works as expected in PHP v5.3+. I tested up to PHP v5.6-beta1. <?php
error_reporting(-1);
ini_set('display_errors', TRUE);
ob_implicit_flush();
ob_start('callback_handler', 0, 0);
ob_implicit_flush(TRUE);
function callback_handler($buffer)
{
file_put_contents(__DIR__.'/temp.log', $buffer);
return $buffer;
}
echo '1,2,3';
ob_flush();
echo ',4,5,6';
ob_flush();
ob_end_clean();
echo ',7,8,9';
/*
* temp.log contains: 1,2,3,4,5,6,7,8,9
*/
/*
* Output = 1,2,3,4,5,6,7,8,9
*/
/*
* Three notices in WP_DEBUG mode were triggered...
*
* Notice: ob_flush(): failed to flush buffer of callback_handler (0) in test2.php on line 18
* Notice: ob_flush(): failed to flush buffer of callback_handler (0) in test2.php on line 22
* Notice: ob_end_clean(): failed to discard buffer of callback_handler (0) in test2.php on line 24
*/ Needs further testing, but if we can update to something like this it might help us...
Based on Example # 2 here: http://www.php.net/manual/en/function.ob-start.php
|
We should also probably consider this WP core routine before making any changes... /**
* Flush all output buffers for PHP 5.2.
*
* Make sure all output buffers are flushed before our singletons our destroyed.
*
* @since 2.2.0
*/
function wp_ob_end_flush_all() {
$levels = ob_get_level();
for ($i=0; $i<$levels; $i++)
ob_end_flush();
}
/**
* Runs just before PHP shuts down execution.
*
* @access private
* @since 1.2.0
*/
function shutdown_action_hook() {
/**
* Fires just before PHP shuts down execution.
*
* @since 1.2.0
*/
do_action( 'shutdown' );
wp_cache_close();
} |
This issue has been closed by wpsharks/comet-cache-pro#17 and this fix, which should greatly improve compatibility with other plugins that use |
https://github.com/wmark/CDN-Linker/blob/master/cdn-linker-base.php NOTE: I reviewed the CDN Linker plugin for any possible conflicts between it's code and QC. It looks solid to me. I'm not seeing any problems with this plugin; but I will try to run some tests against it soon to be sure. I'm seeing that CDN Linker opens an output buffer on We had some reports of a white screen when combining these two plugins. Further testing is needed so that we can try to reproduce that issue, but at this time I'm guessing this is probably caused by another theme or plugin in the mix; which might be closing an output buffer out-of-turn. The latest updates in the QC dev branch should help to detect this being the case. A white screen may still present itself if an output buffer is closed before it should be (in some rare cases), but if |
A white screen could indicate there was an exception thrown by QC. If
|
@JasWSInc I'm the one who reported the white screen issue. On my Multisite debug shows a couple notices which are caused by Domain Mapping plugin which have already been addressed on the plugin support forum (here and here). So, I applied the fixes and my site doesn't show any errors, warnings or notices while the debug is on. However, I can only confirm that the white screen will appear only when Quick Cache & CDN-Linker are activated. I'm using the dev version that @raamdev has provided to me a couple of days ago. Then I have deactivated all other plugins except Quick Cache, CDN-Linker & Domain Mapping. I need the Domain Mapping since it's the MU installation and opposite to the regular WP installations I have this one is still not in the "live stage". However, white screen issue appears even on the regular WP installation (i.e. when the Domain Mapping doesn't exist) so it doesn't seem it's involved in the issue. It's interesting that the issue is occasional and it appears only for the Homepage of the TLD. Let me know if you have any other suggestion that I could take to get you feedback. |
Just to be clear on the above regarding where WP is installed. |
@Sboq Thank you very much for the additional information! Just to be clear: You experience the issue only on sub-domain installs?
Also you mentioned that you were able to reproduce this on a non-MU installation, is that correct? If so, where you testing non-MU on a sub-domain installation (e.g., |
If the WP installation is on the
|
Interesting. I'm going to try to reproduce this in that scenario. Can you tell me what CDN you're using with CDN Linker and any relevant CDN Linker options so that I can attempt to recreate this in an environment that matches yours as closely as possible? If you need to submit anything privately, please use the ticket that you opened earlier. |
Well, I don't know what to add to this issue's title. ;-) Output buffer callbacks get their content chunk-wise. Which is no issue for CDN Linker, no matter what URI you feed it. And, writing files when buffers are about to get flushed is a bad idea, IMHO. I've already made suggestions in my initial comment on how to handle this issue: Assemble the page from chunks the output buffer callback gets — you seem to have figured out how to limit the amount of calls to one at the expense of flushing (→ using |
@wmark writes...
I am researching this issue also. I wanted to touch on this point specifically though. PHP's PHP.net says... http://www.php.net/manual/en/function.ob-start.php
In my tests this seems to hold true. I have not yet seen a case where ob_start('callback_handler', 0, 0);
function callback_handler($buffer, $phase)
{
if($phase !== (PHP_OUTPUT_HANDLER_START | PHP_OUTPUT_HANDLER_END))
// Quick Cache does NOT chunk it's output buffering; so this should never happen.
throw new \exception(sprintf(__('Unexpected OB phase: `%1$s`.', $this->text_domain), $phase));
} Your last comment seems to suggest that you disagree. |
@raamdev I tested CDN Linker on a non-MU install running the latest dev branch of QC Pro and was unable to reproduce an issue. Running WP v3.9 and QC Pro 000000-dev (latest). Plus CDN Linker: https://github.com/wmark/CDN-Linker I will try to run some tests against MU w/ domain mapping enabled later. |
@raamdev I tested CDN Linker on an MU install (sub-directories) running the latest dev branch of QC Pro and was unable to reproduce an issue. Running WP v3.9 and QC Pro 000000-dev (latest). Plus CDN Linker: https://github.com/wmark/CDN-Linker I will run tests with domain mapping enabled next. |
@raamdev @Sboq I was just able to reproduce an issue on a standard non-MU install; related to the output buffering phase. I have not yet pinpointed the exact underlying cause of this, but it seems this exception is being triggered due to ob_start('callback_handler', 0, 0);
function callback_handler($buffer, $phase)
{
if($phase !== (PHP_OUTPUT_HANDLER_START | PHP_OUTPUT_HANDLER_END))
// Quick Cache does NOT chunk it's output buffering; so this should never happen.
throw new \exception(sprintf(__('Unexpected OB phase: `%1$s`.', $this->text_domain), $phase));
}
|
@raamdev Regarding my last message... I cannot find a way to consistently reproduce this issue where the Regarding the QC buffer. Since it's now a locked buffer, there is no explicit call to My suggestion is that we alter this line just a bit to allow for other quirky flags (at least until we can determine what the heck is going on here). I may file a PHP bug report about this also. A locked buffer shouldn't get the Instead of this...
I suggest this... if(!($phase & PHP_OUTPUT_HANDLER_END)) // We do NOT chunk the buffer; so this should NOT occur.
throw new \exception(sprintf(__('Unexpected OB phase: `%1$s`.', $this->text_domain), $phase)); Even this check should not be necessary, because the buffer is locked; and it's not chunked. However, I still think it's best to leave it in place to help catch any remaining edge cases that we've not seen yet. At least then we'll know what may have caused the issue. |
@JasWSInc Thank you for working on this and for the detailed explanation. I merged your Pull Requests with the changes you suggested. |
Quick-Cache does not take into account that functions registered by
ob_start
are callbacks which get output in chunks. Quick-Cache works only iff that chunk constitutes an entire page (or output to the client in general). Else, pages get only cached partially or not at all.Given this minimal example only everything up to and including
</head>
will be cached:Indeed, that minimal example is even good practice to decrease time-to-first-byte!
I suggest that Quick-Cache adds checks to [1] to determine in which phase the callback has been called.
Please see PHP's
ob_get_status
for that:(ob_get_status()['status'] & PHP_OUTPUT_HANDLER_CONT) == PHP_OUTPUT_HANDLER_CONT
is true on calls toob_flush
and I expect that when(ob_get_status()['status'] & PHP_OUTPUT_HANDLER_END) == PHP_OUTPUT_HANDLER_END
is true you will have everything needed for writing cache files.ob_start
Quick-Cache might cache pages which are not completely processed.ob_get_status
does not return everything that is documented:ob_get_status
return undocumented values, and sometimes even omit documented ones. For example, PHP 5.5.3 does not return fieldstatus
at all. Due to a lack of workarounds I suspect that Quick-Cache won't work in with this version of PHP at all.ob_end_flush
yourself.See also [2] and
add_action('wp_head', …)
as well asadd_action('wp_footer', …)
.[1] https://github.com/WebSharks/Quick-Cache/blob/1543fc5efd638b8e9921db9efa14b79a7d9dd036/quick-cache/includes/advanced-cache.tpl.php#L147
[2] https://bugs.php.net/bug.php?id=61272
The text was updated successfully, but these errors were encountered: