Solved

Internal server error 500 caused by timeout

Posted on 2011-02-16
9
581 Views
Last Modified: 2012-05-11
Hi experts,

OK, here's the deal:

php/mysql website.  

User clicks button to send sms out, about 15 to 70 at a time.
php on my site sends data to sms company's site which processes the message sending
meanwhile, my site is left inactive and waiting for a response.
After timeout of 30 seconds, I get an internal 500 error.

I cannot change timeout period (shared server).

Is there any way I can fool my website into thinking it is doing something, until all the messages have been sent?

Thanks,
    Col

0
Comment
Question by:colinspurs
  • 5
  • 3
9 Comments
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 34907191
You can use set_time_limit().  It should work on a shared server.  If your hosting company prohibits this, get a new hosting company!

If you want to post the code that you're using now, maybe we can suggest a new way to send the SMS.
0
 
LVL 3

Author Comment

by:colinspurs
ID: 34907224
Hi Ray,

I think we've been down this road before and up til now I have found a way to stick with my present company - I think you have guessed who that is previously.

I'll see if I can dig out my code.

Col
0
 
LVL 3

Author Comment

by:colinspurs
ID: 34907281
Hope this is enough.  The most I would like to send at a time is currently 80, but I have had to tell my users to send just one team at a time (about 15).  Even this low number causes problems occasionally.

Cheers text-send.php
0
 
LVL 8

Expert Comment

by:rationalboss
ID: 34907293
Just create an <iframe> in your website that would call the script that will process the message. In that script, make sure you use ignore_user_abort(true); see http://www.php.net/ignore_user_abort

Then show a loading image while the iframe is loading. Or maybe set an auto-reload the page to check if the messages have been sent. It would be better if you use an AJAX request to do this.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 108

Accepted Solution

by:
Ray Paseur earned 500 total points
ID: 34907567
Looks like there are only a few places where the delay could be happening.  Line 10 is the data base.  Line 48 is one call to the foreign server.  Line 56 is the other call to the foreign server.  The rest of the script should run at processor speeds.

The problem with using file() and file_get_contents() is that the time required to receive a response is added to your script execution time, and that is why you are getting the timeout conditions -- Clickatell is too slow to respond.  This may be deliberate on their part - they might throttle the rate at which they send messages (in the USA, Twilio has a similar service and they limit it to one message per account per second - it's a spam-control technique).  So if you want to send a lot of messages, you might need a slightly different strategy.  Here is what I would do.

Break this script up into a main script that does the query and a second, separate script that acts as a web service.  The main script will use CURL POST to start one instance of the web service script for each message that needs to be sent.  CURL can start these "mini-scripts" asynchronously and you do not have to wait in the main script for them to complete.  Your request stream may still be throttled, but the failure rate should go w-a-a-a-y down since the throttle will be applied to the web service scripts separately.  You might want to consider using sleep(1), not in the main script, but in the web service script before starting the Clickatell requests.
<?  
require_once("../fobg_txt.inc");
#$fixture_id = 3969;
$sql  = "SELECT P.first_name, P.surname, P.tel_mobile";
$sql .= " FROM fixtures_players FP INNER JOIN players P on FP.fp_player_id = P.id ";
$sql .= " WHERE FP.fp_fixture_id = " . $fixture_id;

#echo "<br />".$sql."<br />";

$sql_query = $db->DB_executeQuery( $sql ); 
			
if(!$sql_query) //If error display error and terminate
{
	echo $sql."<br />";
	echo mysql_error();
	exit;
}			

$no_records = $db->DB_getRecords($sql_query);
if ($no_records == 0)
{
	echo "No players selected for this fixture.";
	exit;
}

while ($row = $db->fetch_Array($sql_query))
{ 
	extract($row);
	$tel_mobile = str_replace(' ','',$tel_mobile);
		
	$text_message  = $first_name . $text_message_bulk;
	#echo "<br />".$text_message."<br />";
	
	if (trim($tel_mobile) == '')
	{
		echo $first_name . " " . $surname . " has no mobile number stored, so no text was sent.<br />";
		continue;
	}
	
/* ***************************/

	$baseurl ="http://api.clickatell.com";
	$text = urlencode($text_message);
	$to = $tel_mobile;
	// auth call
	$url = "$baseurl/http/auth?user=$c_user&password=$c_password&api_id=$c_api_id";
	// do auth call
	$ret = file($url);
	// split our response. return string is on first line of the data returned
	$sess = split(":",$ret[0]);
	if ($sess[0] == "OK") 
	{
		$sess_id = trim($sess[1]); // remove any whitespace
		$url = "$baseurl/http/sendmsg?session_id=$sess_id&to=$to&text=$text";
		// do sendmsg call
		$ret = file($url);
		$send = split(":",$ret[0]);
		if ($send[0] == "ID")
		{
			echo "success message ID: ". $send[1];
	        echo "<br />".$text_message."<br />";
		}
		else
		{
			echo "send message failed";
		}
	} 
	else 
	{
		echo "Authentication failure: ". $ret[0];
		exit();
	}
	#*/ 
}

?>

Open in new window

0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 34907625
As a sidebar note, I think we know where the delay is occurring in this script.  But if you are not sure and you want to time part or all of a script this class comes in handy.
<?php // RAY_oop_stopwatch.php
error_reporting(E_ALL);


// DEMONSTRATE A SCRIPT TIMER FOR ALL OR PART OF A SCRIPT PHP 5+
// MAN PAGE http://us.php.net/manual/en/function.microtime.php


class StopWatch
{
    protected $a, $z;
    public function __construct()
    {
        $this->a = array();
        $this->z = array();
    }

    // A METHOD TO CAPTURE A START TIME
    public function start($name='TIMER')
    {
        $this->a[$name] = microtime(TRUE);
    }

    // A METHOD TO CAPTURE AN END TIME
    public function stop($name='ALL')
    {
        if ($name == 'ALL')
        {
            foreach ($this->a as $name => $start_time)
            {
                if (!isset($this->z[$name])) $this->z[$name] = microtime(TRUE);
            }
        }
        else
        {
            $this->z[$name] = microtime(TRUE);
        }
    }

    // A METHOD TO READ OUT THE TIMER(S)
    public function readout($m=1000, $eol=PHP_EOL)
    {
        $str = NULL;
        foreach ($this->a as $name => $start_time)
        {
            $str .= $name;
            if (!isset($this->z[$name]))
            {
                $str .= " IS STILL RUNNING";
            }
            else
            {
                $lapse_time = $this->z[$name] - $start_time;
                $lapse_msec = $lapse_time * $m;
                $lapse_echo = number_format($lapse_msec, 1);
                $str .= " $lapse_echo";
            }
            $str .= $eol;
        }
        return $str;
    }
}


// INSTANTIATE THE STOPWATCH OBJECT
$sw  = new Stopwatch;

// SET STOPWATCH NAMES
$go = 'GOOGLE ONLY';
$gy = 'GOOGLE AND YAHOO!';
$yo = 'YAHOO! ONLY';

// START SOME TIMERS
$sw->start($go);
$sw->start($gy);

// PERFORM SOME ACTIVITY THAT YOU WANT TO TIME
$page = 'http://google.com';
$html = file_get_contents($page);

// STOP ONE OF THE STOPWATCHES AND START THE OTHER
$sw->stop($go);
$sw->start($yo);

// PERFORM SOME OTHER ACTIVITY THAT YOU WANT TO TIME
$page = 'http://yahoo.com';
$html = file_get_contents($page);

// REPORT THE STOPWATCHES CONTENT (TWO WILL BE INCOMPLETE)
echo nl2br($sw->readout());

// STOP ALL OF THE REMAINING STOPWATCHES
$sw->stop();

// REPORT THE STOPWATCHES CONTENT AGAIN
echo nl2br($sw->readout());

Open in new window

0
 
LVL 3

Author Comment

by:colinspurs
ID: 34916460
Ray, thanks.  I have never come across cURL before and have been reading it up.  I don't think I have the ability to write such a script though.  

Looking at my script again (taken from a Clickatell forum example if I remember rightly) I see that it connects to clickatell for every message to be sent.  Is there a way of just connecting once and scooting thru all the texts in that one session?  If so, would that help?
0
 
LVL 3

Author Comment

by:colinspurs
ID: 34916493
Rationalboss thanks too.  I'm not sure I'd be allowed to set ignore_user_abort(true); Again, AJAX is new to me (I have a lot to learn don't I!).
0
 
LVL 3

Author Comment

by:colinspurs
ID: 35200373
<<a way of just connecting once and scooting thru all the texts in that one session>>

I did that and it has speeded things up.
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

SASS allows you to treat your CSS code in a more OOP way. Let's have a look on how you can structure your code in order for it to be easily maintained and reused.
Is your Office 365 signature not working the way you want it to? Are signature updates taking up too much of your time? Let's run through the most common problems that an IT administrator can encounter when dealing with Office 365 email signatures.
In this tutorial viewers will learn how to style transparent/translucent elements using alpha transparency in CSS Start with a normal styled element, such as a div.: Define its "background-color" property as "rgba (255, 255, 255, .5): The numbers in…
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now