PHP Run function on PHP Timeout - php

I'm working on a script that a server posts to us and we post to a server and theoretically is supposed to receive a response from the server and reply back to the server that posted to us. However sometimes the server I'm posting to doesn't respond. The big problem is the server that posted to us will assume the transaction went through successfully unless it hears otherwise. So essentially I need a way to send a response back to the first server if I never hear back from the server I'm posting to. I think register_shutdown_function could work for me but I don't know how to set that up so it only runs on error or whatever.
Thanks in advance

register_shutdown_function() should work for you. Just use a global variable to determine whether the remote server responded or not:
<?php
function on_shutdown () {
if (!$GLOBALS['complete']) {
// Handle server not responding here
}
}
// Suppress "FATAL ERROR" message when time limit reached
error_reporting(0);
$complete = FALSE;
register_shutdown_function('on_shutdown');
// Code which posts to remote server here
$complete = TRUE;
This means that $complete will still be false if the code which posts to the remote server does not complete, so you can just check the truthyness of $complete in the function that fires on shutdown.

Related

AWS Sns publish silently dies when device is disabled?

I am hitting a strange error when I attempt to call $sns->publish (PHP) - it never returns, I am not sure if it dies silently, but I could not catch an exception or get a return code.
I was able to track this down to happen when device for the token (endpoint) appears to be already disabled in the SNS console. It gets disabled on the initial call, I would assume due to the error returned by GCM that token is invalid.
What am I doing wrong and how can I prevent the problem? I do not want to check every endpoint for being enabled since I may be pushing to 10 out of 1000. However I definitely want to continue executing my push loop.
Any thoughts? AWS team forum seems useless, it has been weeks since original reply by AWS team member asking for code with not response since that time.
you can check if the endpoint is disabled before sending push notification as -
$arn_code = ARN_CODE_HERE;
$arn_arr = array("EndpointArn"=>$arn_code);
$endpointAtt = $sns->getEndpointAttributes($arn_arr);
//print_r($endpointAtt);
if($endpointAtt != 'failed' && $endpointAtt['Attributes']['Enabled'] != 'false')
{
....PUBLISH CODE HERE....
}
It will not stop the execution.
Hope it will help you.

stomp->hasFrame() returning false with messages in the queue

When consuming data from a ActiveMQ queue im running into the following problem
With the following code:
$stomp = new Stomp($activeMQURI);
$stomp->subscribe($queue);
while ($stomp->hasFrame()) {
$frame = $stomp->readFrame();
if ($frame) {
$stomp->ack($frame);
}
}
It will only loop through about 1-10 messages before $stomp->hasFrame() returns false. The problem is there are 10k messages still in the queue!
When i put a delay in after the acknowledgment everything works as expected:
$stomp = new Stomp($activeMQURI);
$stomp->subscribe($queue);
while ($stomp->hasFrame()) {
$frame = $stomp->readFrame();
if ($frame) {
$stomp->ack($frame);
sleep(1);
}
}
I was thinking that this was happening because the ActiveMQ server has not had a chance to process the ack before the consumer (my code) requests another frame. Can anyone explain the real reason why this is happening, and maybe a better fix then SLEEP?
You don't really specify what client you are using so here's a general answer. Most client's provide a blocking receive call either timed or infinite wait which will return when a message arrives, or indicate failure in the timed case. The speed at which the broker is going to dispatch messages to your client depends on a great many factors such as the number of consumers on the destination, the prefetch size set by each consumer, and the speed of the network etc, etc. Your code should not expect immediate turned and be able to deal with the case where there is a lull in message traffic. That's about as good an answer as I can give since I don't know any more about your setup.

php script can be stopped?

I'm trying to make a paypal IPN system, this is a system of paypal to automatically check money transfers. They provide a basic system script to do it.
The system is easy, you get $_POST[] on your script, and then open a socket versus paypal, and they response to you valid or invalid word in the socket.
My problem is that opening the socket, 50% of times i'm getting connection lost. When the script connect, I don't have any problem. So I changed it to 20 trys, instead 1:
<?
//...
mail("mi#mail.com", "subject", "executing", "some headers"); //mailme when this is execute
$try = 20;
do{
$fp = #fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 15);
$try--;
}while($try>0 && !$fp);
if (!$fp) { // HTTP ERROR
mail("mi#mail.com", "subject", "error_message_not_connecting", "some headers");
} else {
mail("mi#mail.com", "subject", "connected_reading_socket", "some headers");
//fputs(..); and the loop reading working.
}
?>
In my test, it works now 100% of severals trys. But in real transfers, it doesn't work 20-30% of times. I'm getting the 1st mail, but never the second one in that fails.
I'm thinking.. If paypal only open the connection to my server 1 second, can the php script stop after some trys, and stop going on? or any idea what is wrong here?
Sending the mail can fail too, especially if you have network issues. You should log the failure conditions, for both mail() as well as your fsockopen, so you can revisit them afterwards.
Also, your fsockopen can get stuck. You have a 15 second timeout and you try 20 times, so your script will work for 20*15=300 seconds = 5 minutes, which is probably longer than your PHP script timeout -> PHP would abort your script mid-process, right? Max execution time is only 30 seconds by default in PHP.
A PHP script can be stopped with exit;.
You can pause the php script proccessing with sleep(nr_sec).
I used to get similar problems. Strange behavior when usin sockets.
Better use CURL instead, it's more stable.
http://leepeng.blogspot.com/2006/04/standard-paypal-php-integration.html
I found the error. A php can be stopped when a users close the conection to the server (usually by click stop button on browser, or in this case a socket closed by paypal).
There are 3 ways to stop a script.
1-by finish the script
2-by user closeing the conection to the server
3-by timeout
I used the function ignore_user_abort(true), and I dont have more problems.
http://php.net/manual/en/function.ignore-user-abort.php

PHP: Detect and show "Server overloaded" message

I have noticed a few websites such as hypem.com show a "You didnt get served" error message when the site is busy rather than just letting people wait, time out or refresh; aggravating what is probably a server load issue.
We are too loaded to process your request. Please click "back" in your
browser and try what you were doing again.
How is this achieved before the server becomes overloaded? It sounds like a really neat way to manage user expectation if a site happens to get overloaded whilst also giving the site time to recover.
Another options is this:
$load = sys_getloadavg();
if ($load[0] > 80) {
header('HTTP/1.1 503 Too busy, try again later');
die('Server too busy. Please try again later.');
}
I got it from php's site http://php.net/sys_getloadavg, altough I'm not sure what the values represent that the sys_getloadavg returns
You could simply create a 500.html file and have your webserver use that whenever a 50x error is thrown.
I.e. in your apache config:
ErrorDocument 500 /errors/500.html
Or use a php shutdown function to check if the request timeout (which defaults to 30s) has been reached and if so - redirect/render something static (so that rendering the error itself cannot cause problems).
Note that most sites where you'll see a "This site is taking too long to respond" message are effectively generating that message with javascript.
This may be to do with the database connection timing out, but that assumes that your server has a bigger DB load than CPU load when times get tough. If this is the case, you can make your DB connector show the message if no connection happens for 1 second.
You could also use a quick query to the logs table to find out how many hits/second there are and automatically not respond to any more after a certain point in order to preserve QOS for the others. In this case, you would have to set that level manually, based on server logs. An alternative method can be seen here in the Drupal throttle module.
Another alternative would be to use the Apache status page to get information on how many child processes are free and to throttle id there are none left as per #giltotherescue's answer to this question.
You can restrict the maximum connection in apache configuration too...
Refer
http://httpd.apache.org/docs/2.2/mod/mpm_common.html#maxclients
http://www.howtoforge.com/configuring_apache_for_maximum_performance
This is not a strictly PHP solution, but you could do like Twitter, i.e.:
serve a mostly static HTML and Javascript app from a CDN or another server of yours
the calls to the actual heavy work server-side (PHP in your case) functions/APIs are actually done in AJAX from one of your static JS files
so you can set a timeout on your AJAX calls and return a "Seems like loading tweets may take longer than expected"-like notice.
You can use the php tick function to detect when a server isn't loading for a specified amount of time, then display an error messages. Basic usage:
<?php
$connection = false;
function checkConnection( $connectionWaitingTime = 3 )
{
// check connection & time
global $time,$connection;
if( ($t = (time() - $time)) >= $connectionWaitingTime && !$connection){
echo ("<p> Server not responding for <strong>$t</strong> seconds !! </p>");
die("Connection aborted");
}
}
register_tick_function("checkConnection");
$time = time();
declare (ticks=1)
{
require 'yourapp.php' // load your main app logic
$connection = true ;
}
The while(true) is just to simulate a loaded server.
To implement the script in your site, you need to remove the while statement and add your page logic E.G dispatch event or front controller action etc.
And the $connectionWaitingTime in the checkCOnnection function is set to timeout after 3 seconds, but you can change that to whatever you want

PHProxy hanging on response

I've been working on a PHProxy server for some time (you can see my recent posts) and I'm at a point where I have everything working except this problem.
do
{
$data = #fread($_socket, 8192);
$_response_body .= $data;
}
while (isset($data{0}));
unset($data);
My proxy server logs into a server running IIS without the user's intervention (you had to verify credentials somewhere else). Upon logging into this site the header requests are constructed and sent but the response waits for 120 seconds on this section of code. After that long period the proxy continues correctly as it is supposed to. The response that I'm waiting on is just a Object has moved here page that gives me a new location. I've verified headers are correct via Wireshark and LiveHttpHeaders. Again, everything IS working, it just takes forever to load this particular page.
Can any PHP developers give me a hint as to what I should be checking for malfunctions?
Thanks,
EDIT:
[17-Jul-2010 12:33:17] BEFORE RESPONSE
[17-Jul-2010 12:35:17] AFTER RESPONSE
It takes 120 seconds exactly. Is something timing out?
This code significantly increases response time, but doesn't identify the main problem of where/who/what is timing out to begin with.
stream_set_timeout($_socket, 1);
do
{
$data = #fread($_socket, 8192); // silenced to avoid the "normal" warning by a faulty SSL connection
$_response_body .= $data;
}
while (isset($data{0}));
unset($data);

Categories