Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to terminate a code part when it's execution time is getting longer than a specified time limit?

I'm currently working on a scheduled tasks (like cronjobs) system in my CMS application. I would like to know if there's any possibility to terminate a piece of code when it's execution time is getting longer than a specified time limit.

Some scheduled tasks may be heavy, a task may run into a infinite loop, to keep it short; there are lots of reasons why tasks could take up a lot of time. One of the few problems with this is that the task would take up much more resources than it actually needs which decreases the performance of the server it's running on, this would make the CMS and the site it self less reliable.

Think of the system as follows: Once the scheduled tasks manager is triggered, it will execute all tasks that where scheduled for that time. Think of a simple for loop which would execute each task, synchronized, one after the other. Think of this simple example bellow:

// This array would contain an array with all scheduled tasks that should be executed.
$tasks = Array();

// Loop through each task
foreach($tasks as $t) {
    // Execute the task
    $t->execute();
}

Now, the $task->execute(); method makes PHP's interpreter wait until the code of the task is executed. My question is if there's any possible way to terminate the code running behind the execute(); method if it's execution time is getting longer than a specified time.

For example, if a time limit of 10 seconds is supplied, and a task is taking more than 30 seconds to execute it's code, the running code of the task should be terminated after 10 seconds to allow the task scheduler to continue to the next task.

It is possible to implement this feature inside the code of each scheduled task with a simple if-statement which checks the time each time a part of the code is being executed. The problem with this is that this needs to be implemented in the code of each task, since this system is meant to be used for 3th party developers to used these kind of tasks properly to implement these with their plugins. I don't like to 'force' all the developers that use the tasks to implement such features.

I know about the set_time_limit(); method PHP supplies, the problem is though that this method would terminate the whole session instead of that one method, this is why this doesn't solve the problem.

like image 774
Tim Visée Avatar asked Mar 21 '23 05:03

Tim Visée


2 Answers

"Porting" my comment to an answer:

This other question is very similar.

PHP, by its default implementation, runs scripts in a single thread so it is impossible to cancel code execution from the script itself.
Only very, very few PHP functions support asynchronous operation, e.g. you can run an asynchronous query with mysqlnd, however this particular feature is part of the mysql driver, not PHP.

There are extensions which introduce multi-threading to PHP, namely pthread.
To recommend yet another source, read this answer by the author of the extension.

Unfortunately, for a "mainstream" project (which should run as good as possible on as generic setups as possible), using pthreads is not do-able.
The extension is unlikely to be installed on any shared webspaces.

Also, keep in mind that thread-safe programming (or scripting for those who care) is a serious task and you have to care for it. This means preparing your threaded code to not lock up waiting for each other (deadlock), corrupt each other's data, etc.
A detailed answer on the term of thread-safety can be found here.

Thoroughly think about the work involved, the risks of messing something up, and the gains of using threading.
Make sure your desire is really important enough to introduce complex threading.

like image 91
Lukas Avatar answered Apr 11 '23 03:04

Lukas


I've encountered this kind of problem, I have a trick that can solve this. My workaround was that, I used cURL to execute the local script like this:

// This is the curl call which will execute the local script
$execute_script = curl_call('local_script.php');

In the 'local_script.php' file is the code to execute

// In local_script.php
// Set time limit
set_time_limit(10);
// Execute task
$task->execute();
// Print 1 to let the curl call know that the script executed at the right time
echo '1';

Then, in the cURL call part, you can check if the script executed just fine when it returns "1"

if ($execute_script == '1'){
  // Successful script
} else {
  // Timed out
}

Hope that helps

like image 29
Ronald Borla Avatar answered Apr 11 '23 03:04

Ronald Borla