Random Blog
Join JournalHome.com.
Create your own free blog today.
Create Your Blog
Flag this entry/bog.
It will be manually reviewed.
Report This!

Journal Home Official Blog

register_shutdown_function(...) doesn't work with ob_gzhandler(...)

Posted in PHP Code

[I have decided to start adding some entries about the re-factoring of journal home, either it will help someone else or someone will be able to offer some comments]

I am busy doing a lot of changes to the code of Journalhome.com to ensure that it runs better than the current software, (that is no longer supported in any case). My aim is to speed up the whole delivery of the page to the browsers.
Some of the tools used to speed up the delivery of pages is compression with things like ob_gzhander and ob_start

The problem with that is that some code that I want to be executed at the very end of the script, (as the script is completing) it does not seem to be executed.

In php when you call ob_start('ob_gzhandler'); it tells the php compiler to take all the output, (everything going to the screen), and, instead of sending it to the screen we will send the string to a function called ob_gzhandler who in turn will return a compressed string.

Normally the way it works is:

Code =//=> PHP compiler=//=> Send to the browser (as soon as code want it to go, we cannot get it back) =//=> Do do some completion code

With ob_start( ... ) it is a litte bit more complex

Code =//=> ob_start( ... )  PHP compiler=//=> ob_end_flush(...) =//=> Send to the browser, (all at once) =//=> Do do some completion code

What this means is that the created page is sent out as one big string to the browser.
In practice, a page is almost always sent as one big chunk of string, but we cannot really control the string that is sent out. So we can call a function to 'handle'  the string and do what we want with it.

Code =//=> ob_start( 'ob_gzhandler' )  PHP compiler=//=> ob_end_flush(...)  =//=>
                                                                                             ob_gzhandler( $str ) { // compress it }  =//=>
                                                                                              
Send that to the browser, (all at once) =//=> Do do some completion code 

The problem with that is the function ob_gzhandler(...) does not seem to allow the "Do do some completion code"

The problem is almost certainly with register_shutdown_function(...), because as the manual clearly says, if any of the registered function call exit() then the processing will stop completely and no other registered function will be called.
So I can only guess that ob_gzhandler(...)  itself registers a function that calls exit(), (of course this is only a guess).

The other bigger problem with that logic, (and kind of backs up my theory), is that it seems to allow _some_of the registered code to be completed. This makes sense as the shutdown functions are called in the order they are registered so the ones registered before ob_start('ob_gzhandler'); will be executed but not the ones after.

For example...

<?php
function foo()
{
  echo "This should be called last";
}

ob_start('ob_gzhandler'); // replace with ob_start(); for it to work
register_shutdown_function('foo');
echo "This is called now<br />";
?>

This works as expected with PHP 5.x and later, but not with php 4.x, (well not with php 4.4.x that I am using).

<?php
function foo1()
{
  echo "This should be called second to last<br />";
}

function foo()
{
  echo "This should be called last<br />";
}

register_shutdown_function('foo1');
ob_start('ob_gzhandler');  // replace with ob_start(); for it to work
register_shutdown_function('foo');
echo "This is called now<br />";
?>

This will also not work with all flavours of php4.x but it will work with php5.x

As I am planning to move to php 5 this is not a problem but I am trying very hard to make sure that he new code works on both 4.x and 5.x, (simply because I want the code to be open source.

The 'fix' I have is to remove the compression altogether with php < 5.x

<?php
function foo()
{
  echo "This should be called last";
}
if( phpversion() < 5.00 )
{
  ob_start();
}
else
{
  ob_start('ob_gzhandler');
}
register_shutdown_function('foo');
echo "This is called now<br />";
?>

Obviously this is not a perfect solution as the code is no longer compressed, but for those that will be using php4, (that is no longer supported btw), then it will have to do.

7:22 AM - 8/6/2008 - comments {3} - post comment


Share and enjoy
  • Digg
  • del.icio.us
  • DZone
  • Netvouz
  • NewsVine
  • Reddit
  • Slashdot
  • StumbleUpon
  • Technorati
  • YahooMyWeb

Description
JournalHome.com has created this blog for the purpose of keeping members and visitors up to date with JournalHome.com site information.
The easiest way to stay up to date is by using the RSS/XML feed.
Place this URL within your rss aggregator and it will automatically update itself whenever a new journal entry is published.
If you have any questions which is not answered within this blog then feel free to contact me or post on our forum.
Calendar
«  November 2008  »
MonTueWedThuFriSatSun
 12
3456789
10111213141516
17181920212223
24252627282930




Home
My Wall
User Profile
Archives
Friends

My Twitter...



Webmaster Forum
Free Blog






Recent Entries
- is GMail only for spammers?
- Turned bad-behavior back on
- Please bear with us, (me)
- Big fan of Radio 1
- register_shutdown_function(...) doesn't work with ob_gzhandler(...)
portfolio