Limit the duration of the call to external scripts - php

I am using Symfony to talk to the Office365 mail server, by calling a Symfony command, in a cronned process (every minute).
Apparently, occasionally something in that communication gets stuck and my php script keeps running - even after the next scheduled call happens, so then I have 2, then 3, then 4 scripts running in parallel.
Question is: how can I reliably limit the total duration of this Symfony command call to max. of 1 minute?
I'm saying "total duration" because I did try with setting the max_execution_time, that is the set_time_limit(60), but apparently this setting doesn't count in any externals calls to other scripts - so any wait for the MX server to respond wouldn't be calculated.
I also thought to try with setting the max_input_time but that didn't work in my case, out of 2 reasons: 1. apparently Symfony console somehow overwrites my regular php.ini value with a -1 and 2. I cannot set this setting manually inside the Symfony script. What ever I set to it, with ini_set("max_input_time", XX), it stays on the "infinite" value (of -1). Thank you!

but apparently this setting doesn't count in any externals calls to other scripts
Indeed, as by https://www.php.net/manual/en/function.set-time-limit.php
The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running. This is not true on Windows where the measured time is real.
How about setting a timeout for the call to API? If you use Guzzle, https://docs.guzzlephp.org/en/stable/request-options.html#timeout
// Timeout if a server does not return a response in 3.14 seconds.
$client->request('GET', '/delay/5', ['timeout' => 3.14]);
And then you must make sure the limit you set by set_time_limit() + the timeout is less than the time interval reserved for running the script by the cron.

Related

set_time_limit does not work to create a timeout [duplicate]

I have two questions concerning the sleep() function in PHP:
Does the sleep time affect the maximum execution time limit of my PHP scripts? Sometimes, PHP shows the message "maximum execution time of 30 seconds exceeded". Will this message appear if I use sleep(31)?
Are there any risks when using the sleep()function? Does it cost a lot of CPU performance?
You should try it, just have a script that sleeps for more than your maximum execution time.
<?php
sleep(ini_get('max_execution_time') + 10);
?>
Spoiler: Under Linux, sleeping time is ignored, but under Windows, it counts as execution time.
It only affects script time not system calls like sleep(). There is apparently a bug where on Windows sleep() is included. Max execution time is about real-time, not CPU time or anything like that. You can change it however:
max_execution_time directive in your php.ini. This is a global setting;
Using ini_set() with the above directive. This will change it only for the currently executing script only for that execution;
set_time_limit(): also a local change.
As for the difference between the last two, I believe max_execution_time is a fixed quantity. Running:
ini_set('max_execution_time', 60);
will limit to the script to 60 seconds. If after 20 seconds you call:
set_time_limit(60);
the script will now be limited to 20 + 60 = 80 seconds.
From the PHP sleep() page, there's this user-contributed note:
Note: The set_time_limit() function
and the configuration directive
max_execution_time only affect the
execution time of the script itself.
Any time spent on activity that
happens outside the execution of the
script such as system calls using
system(), the sleep() function,
database queries, etc. is not included
when determining the maximum time that
the script has been running.
Others have already covered the basics of sleep() and PHP script execution time limit, but you should also be aware of another risk when using really long sleep periods.
Usually, when a browser sends a request to a server and does not receive any data from the server, the connection can time out. This time limit depends on the browser's configurations, but I've read that IE7 has a default value of just 30 seconds, while Firefox has a default value of 115 seconds--you can check your own configuration in Firefox by going to about:config and filtering for network.http.keep-alive.timeout (the time limit is specified in seconds).
Edit: I had the units for network.http.keep-alive.timeout and browser.urlbar.search.timeout mixed up. It is indeed in seconds, not tenths of a second.
a) Yes, it counts toward the time limit (so sleep(31) will trigger an error)
b) It does the opposite of costing CPU performance - it lets other applications use the CPU (when an application sleeps, the CPU usage of that application will be near 0%). Aside from taking time away from the user, I can't really think of any risks of using this.

About max execution timeout

I have some question on server response max execution timeout.
If, I called server API to running something huge and not able to finish within time limit set in server php.ini max_execution_time config, will the process in server still continue to process?
- if so, will it process endless?
- if not, is the process stop immediately or canceling loop one by one and finish all process.
In my experience, when I receive max execution timeout on local hosting, the data is already process.
So I not sure it is because it is stuck on response until timeout or server is continue running after throw max execution timeout exception.
It really depends on what your PHP code is like.
Usually the code execution will halt. You can alter this behaviour using ignore_user_abort().
PHP interpreter runs scripts against php.ini configuration and checks max_execution_time = 500 and max_input_time = 500.
PHP doesn't continue to run the script after the max_execution_time. It's simply "kills" the script.
What can also happen, script starts a database query, normally query will run on database server until finished no-matter what happens to the script. Also you may get a Gateway Timeout coming from the web server, for Apache check httpd.conf and look for the setting Timeout.
If you need to run a script that takes time to execute, a lot more then the rest of your website, you should call a web page, PHP on server, fork a new process as a background executed script (the PHP part that takes lot of time), inform user via async status updates or sending an email that processing ended. You should not extend max_execution_time for all script just for one exception.
It doesn't continue after the exception is thrown. It's simply cut when the time is up.
Anything before the time out is executed. If not designed especially to precent this.
The process won't continue and stop immediately after the time limit set in server php.ini max_executiontime config has been reached then php throw a max execution timeout exception.
Here (How to increase maximum execution time in php) if you want to increase maximum execution time in php file.

PHP max_execution_time shows but not works [duplicate]

I have two questions concerning the sleep() function in PHP:
Does the sleep time affect the maximum execution time limit of my PHP scripts? Sometimes, PHP shows the message "maximum execution time of 30 seconds exceeded". Will this message appear if I use sleep(31)?
Are there any risks when using the sleep()function? Does it cost a lot of CPU performance?
You should try it, just have a script that sleeps for more than your maximum execution time.
<?php
sleep(ini_get('max_execution_time') + 10);
?>
Spoiler: Under Linux, sleeping time is ignored, but under Windows, it counts as execution time.
It only affects script time not system calls like sleep(). There is apparently a bug where on Windows sleep() is included. Max execution time is about real-time, not CPU time or anything like that. You can change it however:
max_execution_time directive in your php.ini. This is a global setting;
Using ini_set() with the above directive. This will change it only for the currently executing script only for that execution;
set_time_limit(): also a local change.
As for the difference between the last two, I believe max_execution_time is a fixed quantity. Running:
ini_set('max_execution_time', 60);
will limit to the script to 60 seconds. If after 20 seconds you call:
set_time_limit(60);
the script will now be limited to 20 + 60 = 80 seconds.
From the PHP sleep() page, there's this user-contributed note:
Note: The set_time_limit() function
and the configuration directive
max_execution_time only affect the
execution time of the script itself.
Any time spent on activity that
happens outside the execution of the
script such as system calls using
system(), the sleep() function,
database queries, etc. is not included
when determining the maximum time that
the script has been running.
Others have already covered the basics of sleep() and PHP script execution time limit, but you should also be aware of another risk when using really long sleep periods.
Usually, when a browser sends a request to a server and does not receive any data from the server, the connection can time out. This time limit depends on the browser's configurations, but I've read that IE7 has a default value of just 30 seconds, while Firefox has a default value of 115 seconds--you can check your own configuration in Firefox by going to about:config and filtering for network.http.keep-alive.timeout (the time limit is specified in seconds).
Edit: I had the units for network.http.keep-alive.timeout and browser.urlbar.search.timeout mixed up. It is indeed in seconds, not tenths of a second.
a) Yes, it counts toward the time limit (so sleep(31) will trigger an error)
b) It does the opposite of costing CPU performance - it lets other applications use the CPU (when an application sleeps, the CPU usage of that application will be near 0%). Aside from taking time away from the user, I can't really think of any risks of using this.

CRON script timing out on AWS ubuntu -- php.ini files look good, where else should I check? (timeout)

I have a cron script which calls a PHP file every minute. That file checks to see if any actions need to be taken and, if so, takes those actions. When the execution time is long, however, this script doesn't always finish. I'm not seeing any error codes, and my built-in logging simply stops, since it only runs with the file being executed.
The thing is: the amount of time varies over a dozen seconds in range, so I'm not sure if it's 300 seconds to my timeout when sometimes the script seems to quit after just 280.
This is being run on an AWS ubuntu server.
Is there a list of all the places I might check for errors or timeouts? The two php.ini files are both set to a half-hour, and my script is not running for nearly that long.

PHP executes longer than max_execution_time... sometimes

I have a PHP class, once called, sets the time limit to 60 seconds. The only special thing about this class is that it uses curl_multi_exec().
set_time_limit(60);
ini_set('max_execution_time', 60);
The problem is that under Apache's /server-status page, this page and another one that uses single threaded curl run past their max_execution_time and reach up to 200 seconds, sometimes!
What am I missing? Is there a way to setup Apache to terminate scripts (or even connections) running for longer than say 90 seconds?
From the manual:
The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running.
Because curl requests fall under this category, time spent waiting for a request to complete will not be counted. You should set the curl setting CURLOPT_TIMEOUT to a lower value, or monitor the time spent in executing your script yourself.
Aha! When you set that configuration, the ticker resets itself, example:
sleep(10);
set_time_limit(20);
sleep(10);
set_time_limit(5);
sleep(10); // dies after 5 seconds
Total running time is ~30s.
With regards to curl_exec_multi, you can set the CURL timeout option instead of the PHP one. This depends on who would rather die in your opinion - the curl connection, or the full request.

Categories