l008com Posted December 26, 2020 Share Posted December 26, 2020 I have a script that runs periodically by a launchd timer. I give the script a very tight timeout ( set_time_limit(120); ). Most of the time, my script works great. But every once in a while, one of the commands I run in an exec( ) call seems to hang. This of course is a problem because once the exec( ) call hangs, the php script hangs as time spent on exec( ) calls does not count towards the script's runtime. Furthermore since the script is still running, launchd doesn't call it again. So in this way, my script is entirely at the mercy of a command line program not having a problem. And if it does, I can't do anything about it. So while I could try to figure out why my particular command seems to go awry (which is its own weird issue), the bigger issue is how can I call command line programs in php in a way that don't allow a runaway command to lock up the whole script forever? I wish there was an exec( )-type function with timeout built in. Or even a script timelimit function that DID count pauses and external programs. Something to kill this!? Something other than a SECOND php script that would check on the first script and kill it when there is a problem. There MUST be a better solution than that? Any thoughts? Quote Link to comment https://forums.phpfreaks.com/topic/311927-protecting-php-from-hung-cli-calls/ Share on other sites More sharing options...
requinix Posted December 26, 2020 Share Posted December 26, 2020 It wouldn't have to be a second script. All you'd have to do is edit the main script right near the beginning so that it forks, does a timed (120s) wait while the child runs, then if the time expires it sends a term signal to the child. But don't bother. Use timeout(1) for the problematic command. Quote Link to comment https://forums.phpfreaks.com/topic/311927-protecting-php-from-hung-cli-calls/#findComment-1583433 Share on other sites More sharing options...
kicken Posted December 27, 2020 Share Posted December 27, 2020 (edited) The timeout command would be the easiest way to handle this probably. I didn't know that was a thing, good to know. If for some reason that wasn't an option, you should be able to use proc_open and proc_terminate to accomplish the same task. I don't have time ATM to try it and provide an example. If I do later I may post an example. Edited December 27, 2020 by kicken Quote Link to comment https://forums.phpfreaks.com/topic/311927-protecting-php-from-hung-cli-calls/#findComment-1583438 Share on other sites More sharing options...
requinix Posted December 27, 2020 Share Posted December 27, 2020 1 hour ago, kicken said: If for some reason that wasn't an option, you should be able to use proc_open and proc_terminate to accomplish the same task. I don't have time ATM to try it and provide an example. If I do later I may post an example. It gives more control, but one feature it doesn't have is a way to wait for the process to close or a timeout to expire. So unless I missed something, that means having to poll the process every couple seconds to see if it's still going, then giving up and terminating it if the 120s has passed. Quote Link to comment https://forums.phpfreaks.com/topic/311927-protecting-php-from-hung-cli-calls/#findComment-1583439 Share on other sites More sharing options...
kicken Posted December 27, 2020 Share Posted December 27, 2020 15 hours ago, requinix said: So unless I missed something, Nope, polling the process status is what I was speaking of. With proc_open such a thing is possible where as with exec you're just stuck until the process is done. Polling for the status isn't an ideal solution, but it's a solution if that timeout command isn't available (ie, on windows). function run_with_timeout($cmd, $timeout = 30){ $handle = proc_open($cmd, [['pipe', 'r'], STDOUT, STDERR], $pipes); if (!$handle){ throw new \RuntimeException('Unable to launch process'); } fclose($pipes[0]); $start = time(); try { do { usleep(500 * 1000); $status = proc_get_status($handle); } while ($status['running'] && time() - $start < $timeout); if ($status['running']){ proc_terminate($handle); throw new \RuntimeException('Timeout'); } return $status['exitcode']; } finally { proc_close($handle); } } Quote Link to comment https://forums.phpfreaks.com/topic/311927-protecting-php-from-hung-cli-calls/#findComment-1583448 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.