Hi Rasmus,
This may be a little bit long, sorry for taking your time.
It still does not work as expected. I tried some experiment, and found that
if I called some function or write some code line other then calling
header(), the register_shutdown_function and other part of codes work as
expected . For example:
<?php
set_time_limit(5);
function f(){
set_time_limit(10);
//doing something time consuming
}
some_function();
?>
The time limit of 5 will be the limit of the some_function() and the 10 will
be the limit of function f() respectively.
Code example:
-----------------------------------------------------------------------------------------------------------------------
<?php
set_time_limit(1);
ignore_user_abort(true);
function say_goodbye() {
$st = connection_status();
print "Status 1: ".$st."\n";
set_time_limit(10);
$st = connection_status();
print "Status 2: ".$st."\n";
$count=20000000;
for($i=0; $i<$count; $i++){ }
print "End!\n";
exec("touch /home/.nappy/liang/liang.ns2user.info/php/bbb");
}
register_shutdown_function("say_goodbye");
print "Sleeping...\n";
$count=10000000;
for($i=0; $i<$count; $i++){ }
print "Done!\n";
?>
------------------------------------------------------------------------------------------------------------------------
-bash-2.05b$ curl -N liang.ns2user.info/php/v.php
Sleeping...
<br />
<b>Fatal error</b>: Maximum execution time of 1 second exceeded in
<b>/home/.nappy/liang/liang.ns2user.info/php/v.php</b> on line <b>30</b><br
/>
Status 1: 2
Status 2: 2
End!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if I change the time limit from 10 to 5 in function f()
-bash-2.05b$ curl -N liang.ns2user.info/php/v.php
Sleeping...
<br />
<b>Fatal error</b>: Maximum execution time of 1 second exceeded in
<b>/home/.nappy/liang/liang.ns2user.info/php/v.php</b> on line <b>30</b><br
/>
Status 1: 2
Status 2: 2
<br />
<b>Fatal error</b>: Maximum execution time of 5 seconds exceeded in
<b>/home/.nappy/liang/liang.ns2user.info/php/v.php</b> on line <b>14</b><br
/>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Change both the time limit to 10 will result:
-bash-2.05b$ curl -N liang.ns2user.info/php/v.php
Sleeping...
Done!
Status 1: 0
Status 2: 0
End!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
But if the some_function is header() then the rule above does not work. It
seems the function f()'s time limit also rule the header(). Only after the
registered shutdown function finishes runing normally or by hit the expire
time limit, will the header() return page to browser/http user agent.
Example code with suggestion from Rasmus as:
------------------------------------------------------------------------------------------------------------------
<?php
set_time_limit(5);
function f(){
set_time_limit(100);
$count=500000000;
for($i=0; $i<$count; $i++){
//sit here and loop for a bit so we can have time to hit Stop...
echo "a \n"; flush();
}
echo "end";
exec("touch /tmp/aaa");
}
register_shutdown_function('f');
ignore_user_abort(true);
header("Content-type: text/plain");
header("Location: y.html");
echo "foo\n"; flush();
for($i=0;$i<10;$i++) { echo $i; sleep(1); }
$fp = fopen("/tmp/foo.txt","a");
fputs($fp,$i);
fclose($fp);
?>
------------------------------------------------------------------------------------------------------------------
After the file /tmp/foo.txt has been created, before the file /tmp/aaa being
created, the y.html will not get to the browser or perl program using
LWP::UserAgent. I think it is no way to close the connection actively by the
php program to deliver the page sooner to end the http request, even I add
lines and make code like this does not work:
----------------------------------------------------------------
header("Content-type: text/plain");
header("Cache-Control: no-store, no-cache");
header("Location: y.html");
header("Connection: close");
----------------------------------------------------------------
My project act as a broker for user agent to a library database server
called z39.50. Upon the request from user agent, my program need to connect
a z39.50 server, getting data back 1 by 1, transforming to sepcial xml
format and sending back to the request party. When the data repository is
huge (sometimes up to million records), I have to get partial data transform
and send back to user agent (normally a piece of perl code, called
harvester) with a resumption token. The harvester will in a while loop send
out another http request with the last resumption token and fetch data of
next part, until finish all data fetching. The time to connect the database
and do the query is a constant overhead. So it is not a good design that
program need to connect the database and query upon each request with or
with out resumption token. So my design is to connect to database and query
only when the first initial request comes, and reponse back with partical
data using header() and continue getting back data from z39 server. Upon
next request, the program will only need to make sure the data needed has
already stored in the harddrive and transform them and send them back.
Since the user harvester agent normally has a 180 second timeout, it is
necessary to respond within that period of time.
I really need your suggestion. Thank you very much again.
Liang
Try somthing lik
e this:
<?php
ignore_user_abort(true);
header("Location: redirect2.html");
echo "foo\n"; flush();
for($i=0;$i<10;$i++) { echo $i; sleep(1); }
$fp = fopen("/tmp/foo.txt","a");
fputs($fp,$i);
fclose($fp);
?>
Liang ZHONG wrote:
> Sorry, does not seem to work here. The code below takes minutes to show
> up in browser.
>
> Any more suggestion?
>
---------------------------------------------------------------------------------------
>
> <?php
>
> set_time_limit(5);
>
> function f(){
> set_time_limit(100);
> $count=500000000;
> for($i=0; $i<$count; $i++){ }
> echo "end";
> exec("touch /home/.nappy/liang/liang.ns2user.info/php/aaa");
> }
>
> register_shutdown_function('f');
>
> ignore_user_abort(true);
> header("Content-type: text/plain");
> header("Location: y.html");
>
> $count=50000;
> for($i=0; $i<$count; $i++){ echo " \n"; }
> flush();
> ?>
>
---------------------------------------------------------------------------------------
>
>
> Liang
>
>>
>> If you don't flush some output after setting the header() then the
>> headers won't go out until the end of the request. So do something
like:
>>
>> ignore_user_abort(true);
>> header("Location: http://whatever");
>> echo "foo\n"; flush();
>>
>> Then whatever comes after this should run and the browser is long gone.
>>
>> -Rasmus
>>
>>
>> Liang ZHONG wrote:
>> > I think I did not express myself clearly.
>> >
>> > What I want is to be able to redirect user an existing page (let them
>> > get it immediately), and to close the connection actively, NOT
>> passively
>> > by user abort, at last, to run the function in background.
>> >
>> > But the redirecting using function header() with location has a
problem
>> > that header() always does return the page to user after the entire
>> > program, including registered showdown function finish running,
>> which is
>> > against the will. I put a time consuming task into a function that
>> > registered to be a shutdown function and hoping it runs after the
user
>> > has got the redirected page and the connection has been closed. But
>> > experiements (using browsers, curl command line tool as well as
>> > perl::LWP code) show that the user got the redirected page only after
>> > the shutdown function finished, which is against the description of
>> > register_shutdown_function at php website.
>> >
>> > It seems only header() function use to redirect page has this problem
>> > (not executed until register_shutdown_function finished) while other
>> > functions like print()/echo(), exec() have not.
>> >
>> > The code looks like:
>> >
>>
---------------------------------------------------------------------------------------------
>>
>> >
>> > <?php
>> > set_time_limit(1);
>> >
>> > function f(){
>> > set_time_limit(20);
>> > $count=50000000;
>> > for($i=0; $i<$count; $i++){ }
>> > echo "end";
>> > exec("touch /home/.nappy/liang/liang.ns2user.info/php/aaa");
>> > }
>> >
>> > register_shutdown_function('f');
>> >
>> > header("Content-type: text/plain");
>> > header("Location: y.html");
>> > ?>
>> >
>>
---------------------------------------------------------------------------------------------
>>
>> >
>> >
>> > http client who sends the request to the php program will only get
the
>> > page back as response after function f finsihes (file aaa created).
>> > Changing the $count will make a lot difference.
>> >
>> > My BIGGEST question is:
>> > How to make user get the redirect page immediately after the
>> header() is
>> > called, and not until function f() ends, while making sure that the
>> > function f() will finally fully (and might slowly) execute?
>> >
>> > Thank you very much for kindly replying.
>> >
>> > With high respect,
>> >
>> > Liang
>> >
>> >
>> >>
>> >> Liang ZHONG wrote:
>> >> > My Question is:
>> >> > What is the correct way to keep the function running after I
>> >> redirect an
>> >> > existing page to http client (which I want the client get
>> immediately)
>> >> > and then immediately close the connection?
>> >>
>> >> ignore_user_abort(true);
>> >>
>> >> -Rasmus
>> >>
>> >> --
>> >> PHP General Mailing List (http://www.php.net/)
>> >> To unsubscribe, visit: http://www.php.net/unsub.php
>> >>
>> >
>>
>> --
>> PHP General Mailing List (http://www.php.net/)
>> To unsubscribe, visit: http://www.php.net/unsub.php
>>
>
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php