Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Timeout a function in PHP

Is there a way to timeout a function? I have 10 minutes to perform a job. The job includes a for loop, here is an example:

<?php
foreach($arr as $key => $value){
   some_function($key, $value); //This function does SSH and SFTP stuff
}
?>

$arr has 15 elements and some_function() sometimes may take more than 1 minutes. In fact once it got hanged for 5 minutes.

Is there a way I can timeout the function call and move on with next element in $arr?

Thank you!!

like image 593
Mo3z Avatar asked May 14 '12 16:05

Mo3z


People also ask

How to set a time out function in PHP?

php $startTime=time(); foreach($arr as $key => $value){ some_function($key, $value); //This function does SSH and SFTP stuff if (time()-$startTime>60) break; //change 60 to the max time, in seconds. }

How to use set_ time_ limit in PHP?

When called, set_time_limit() restarts the timeout counter from zero. In other words, if the timeout is the default 30 seconds, and 25 seconds into script execution a call such as set_time_limit(20) is made, the script will run for a total of 45 seconds before timing out.

What does set_time_limit 0 mean?

Syntax: set_time_limit ( int $seconds ) Return Value: Boolean ( True or False ) Default value:30 seconds. For the maximum or you can say for the infinite execution time, we can set the function with the 0 value. If the value is 0 then it will run for an infinite time.

What is the code to set a 25 seconds read timeout for a stream in PHP?

stream_set_timeout($socket,$sec,$usec);


4 Answers

It depends on your implementation. 99% of the functions in PHP are blocking. Meaning processing will not continue until the current function has completed. However, if the function contains a loop you can add in your own code to interrupt the loop after a certain condition has been met.

Something like this:

foreach ($array as $value) {   perform_task($value); }  function perform_task($value) {   $start_time = time();    while(true) {     if ((time() - $start_time) > 300) {       return false; // timeout, function took longer than 300 seconds     }     // Other processing   } } 

Another example where interrupting the processing IS NOT possible:

foreach ($array as $value) {   perform_task($value); }  function perform_task($value) {     // preg_replace is a blocking function     // There's no way to break out of it after a certain amount of time.     return preg_replace('/pattern/', 'replace', $value); } 
like image 182
Mike B Avatar answered Oct 11 '22 04:10

Mike B


What you want is to use the pcntl_alarm function, which will trigger a SIGALRM signal on timeout.

For example:

// 10 minutes pcntl_alarm( 600 ); pcntl_signal(SIGALRM, function() { print( "Timed-out!\n" ); exit( 0 ); }); 

Please see here the PHP manual for more on this: http://php.net/manual/en/function.pcntl-alarm.php

like image 39
Jacques Avatar answered Oct 11 '22 04:10

Jacques


PHP is single threaded... you have to use your OS's ability to fork another process.

The only way I know how to do this is with the exec command to fork off another full process. Put the stuff you want timed in a separate script, call exec on the script, then immediately sleep for 10 min. If at 10 min the process is still running kill it. (you should have it's PID by making the command run the new php code in the background, getting it via command line and returning it from the exec command).

like image 30
Ray Avatar answered Oct 11 '22 05:10

Ray


You could try implementing this using 'curl'. Curl is -- from PHP -- mostly used to do HTTP/FTP stuff, but it supports many more protocols, including ssh/sftp. I've never done something ssh/sftp related using curl, so i can not give any additional advice, but you should be able to find additional information here on stackoverflow or somewhere else.

There is an option "CURLOPT_TIMEOUT" you could use to configure the timeout for your request (there's also an option "CURLOPT_CONNECTTIMEOUT"). You can even specify the timeouts in millisecond resolution (CURLOPT_TIMEOUT_MS / CURLOPT_CONNECTTIMEOUT_MS).

Anyway: for a cronjob i would recommend to use an additional "lock-file" your script writes when it's started and removes, when it's finished running. You can check for this lock-file within your script so if cron triggers your script before the last run finished, you can just exit your script without any further doing. That ensures, that your script will not be executed multiple times in parallel.

You can find more on the CURL options and CURL itself in the PHP documentation, too:

  • http://www.php.net/manual/en/function.curl-setopt.php
  • http://www.php.net/manual/en/book.curl.php

You have to make sure, that your installed libcurl and/or curl for php supports SSH/SFTP, though:

  • SFTP from PHP - undefined constant CURLOPT_PROTOCOLS and CURLPROTO_SFTP?
  • SFTP from within PHP

etc.

Hope that helps ...

like image 43
aurora Avatar answered Oct 11 '22 03:10

aurora