
helices
Members-
Posts
10 -
Joined
-
Last visited
helices's Achievements

Newbie (1/5)
0
Reputation
-
How to interrupt function execution after X seconds?
helices replied to helices's topic in PHP Coding Help
For those who come here later, I have found a solution. I could not find a solution using alarms. Instead, my solution forks a 2nd process to time the 1st. The only problem I've not resolved is eliminating the annoying text "Terminated" from main script output ... #!/usr/bin/php <?php // GLOBALS $CHILD_PID = 0; $PID = getmypid(); $TIMEOUT = 5; // number of seconds to timeout echo "TIMER: {$TIMEOUT} seconds\n\n"; // Make sure program execution doesn't time out // If set to (0), no time limit is imposed set_time_limit(0); // Begin timer here set_timeout(); // Do system stuff here echo "Doing STUFF here\n\n"; extProg(); // End timer here clear_timeout($CHILD_PID); echo "STUFF is _COMPLETE_ here\n\n"; exit(0); // Stop timer function clear_timeout($CHILD_PID) { posix_kill($CHILD_PID, SIGTERM); } // Execute external program function extProg () { $ldir = 'abcdef'; $prog = "/usr/bin/lftp -e \"cd /_DIR_/;pwd;cls -lrt;\" -u '_ACCOUNT_,bogus' sftp://DOMAIN.com"; $sdir = 'uvwxyz'; $fd = array( 1 => array("pipe", "w"), // stdout 2 => array("pipe", "w"), // stderr ); $proc = proc_open($prog, $fd, $pipes, $ldir, null); $stdout = stream_get_contents($pipes[1]); fclose($pipes[1]); $stderr = explode("\n",stream_get_contents($pipes[2])); fclose($pipes[2]); proc_close($proc); $err = $stderr[0]; if ($sdir != '/') { $str = "cd ok, cwd={$sdir}"; if ($stderr[0] == $str) $err = $stderr[1]; } if ($err > '') return $err; return 0; } // Set timeout timer function set_timeout() { global $CHILD_PID; global $PID; global $TIMEOUT; $CHILD_PID = pcntl_fork(); if($CHILD_PID == 0) { sleep($TIMEOUT); posix_kill($PID, SIGTERM); echo "ERROR: extProg() stopped after {$TIMEOUT} seconds: "; exit(999); } } ?> Of course, I have "dummied up" the lftp connection parameters - suffice it to say that, with my real world parameters, this script throws an error, stops the lftp process and exits as I see fit Any ideas how to silence the errant text output? ~ Mike -
How to interrupt function execution after X seconds?
helices replied to helices's topic in PHP Coding Help
I have; but, I'm reading them again and not seeing anything jump out at me By "notes," are you referring to this? http://php.net/manual/en/function.proc-open.php#refsect1-function.proc-open-notes Or, User Contributed Notes: http://php.net/manual/en/function.proc-open.php#usernotes If the former, are you suggesting that I ought to use popen() instead of proc_open() ? If the latter, please, point me to the specific user note that you mean. Thank you. -
How to interrupt function execution after X seconds?
helices replied to helices's topic in PHP Coding Help
Is this better? #!/usr/bin/php <?php $count = 0; $interval = 1; ### $interval = 5; $max = 5; ### $max = 10; $time = 7; # $time = 20; ### $time = 900; $one = alarm_test(); echo "\n\tONE: {$one}\n\n"; $two = post_alarm(); echo "\n\tTWO: {$two}\n\n"; function post_alarm() { global $count, $interval, $time; $max = $time + 10; while ( $count < $max ) { $count += $interval; print $count."\n"; sleep($interval); } return($count); } function alarm_test() { global $count, $interval, $max, $time; declare(ticks=1); pcntl_signal(SIGALRM, "signal_handler"); pcntl_signal(SIGINT, "signal_handler"); pcntl_signal(SIGQUIT, "signal_handler"); pcntl_signal(SIGTERM, "signal_handler"); pcntl_alarm($time); # Execute time sensitive stuff HERE: while ( $count < $max ) { $count += $interval; print $count."\n"; sleep($interval); } # Any call to pcntl_alarm() will cancel any previously set alarm # If seconds is zero, no new alarm is created pcntl_alarm(0); echo "\n\tAlarm is RESET - We can do something else NOT time sensitive\n\n"; return($max); } function signal_handler($signal) { switch($signal) { case SIGTERM: echo "Caught SIGTERM\n"; exit; case SIGQUIT: echo "Caught SIGQUIT\n"; exit; case SIGINT: echo "Caught SIGINT\n"; exit; case SIGALRM: echo "\nCaught SIGALRM!\n"; echo "DO SOMETHING HERE ...\n\n"; exit; } } ?> function extProg ($array) { $ldir = $array['local_directory']; $prog = $array['prog']; $sdir = $array['remote_dir']; $fd = array( 1 => array("pipe", "w"), // stdout 2 => array("pipe", "w"), // stderr ); $proc = proc_open($prog, $fd, $pipes, $ldir, null); $stdout = stream_get_contents($pipes[1]); fclose($pipes[1]); $stderr = explode("\n",stream_get_contents($pipes[2])); fclose($pipes[2]); proc_close($proc); $err = $stderr[0]; if ($sdir != '/') { $str = "cd ok, cwd={$sdir}"; if ($stderr[0] == $str) $err = $stderr[1]; } if ($err > '') return $err; return 0; } -
How to interrupt function execution after X seconds?
helices replied to helices's topic in PHP Coding Help
OK, I'm sorry for being abrasive today. If I can find a code example that works without a "loop" to increment ticks, I can take it from there. I don't know why alarm in PHP doesn't work like it does in system and Perl. The following test script does what I want, except I must replace the while() loop with the function call to proc_open(): #!/usr/bin/php <?php $count = 0; $interval = 1; ### $interval = 5; $max = 5; ### $max = 10; $time = 7; # $time = 20; ### $time = 900; $one = alarm_test(); echo "\n\tONE: {$one}\n\n"; $two = post_alarm(); echo "\n\tTWO: {$two}\n\n"; function post_alarm() { global $count, $interval, $time; $max = $time + 10; while ( $count < $max ) { $count += $interval; print $count."\n"; sleep($interval); } return($count); } function alarm_test() { global $count, $interval, $max, $time; declare(ticks=1); pcntl_signal(SIGALRM, "signal_handler"); pcntl_signal(SIGINT, "signal_handler"); pcntl_signal(SIGQUIT, "signal_handler"); pcntl_signal(SIGTERM, "signal_handler"); pcntl_alarm($time); # Execute time sensitive stuff HERE: while ( $count < $max ) { $count += $interval; print $count."\n"; sleep($interval); } # Any call to pcntl_alarm() will cancel any previously set alarm # If seconds is zero, no new alarm is created pcntl_alarm(0); echo "\n\tAlarm is RESET - We can do something else NOT time sensitive\n\n"; return($max); } function signal_handler($signal) { switch($signal) { case SIGTERM: echo "Caught SIGTERM\n"; exit; case SIGQUIT: echo "Caught SIGQUIT\n"; exit; case SIGINT: echo "Caught SIGINT\n"; exit; case SIGALRM: echo "\nCaught SIGALRM!\n"; echo "DO SOMETHING HERE ...\n\n"; exit; } } ?> Following is the function that calls proc_open() from one of many scripts that have worked for more than 10,000 times, with the rare (less than 1 in 500 times) case of taking "too long:" function extProg ($array) { $ldir = $array['local_directory']; $prog = $array['prog']; $sdir = $array['remote_dir']; $fd = array( 1 => array("pipe", "w"), // stdout 2 => array("pipe", "w"), // stderr ); $proc = proc_open($prog, $fd, $pipes, $ldir, null); $stdout = stream_get_contents($pipes[1]); fclose($pipes[1]); $stderr = explode("\n",stream_get_contents($pipes[2])); fclose($pipes[2]); proc_close($proc); $err = $stderr[0]; if ($sdir != '/') { $str = "cd ok, cwd={$sdir}"; if ($stderr[0] == $str) $err = $stderr[1]; } if ($err > '') return $err; return 0; } Does this suffice for my code examples? Thank you. ~ Mike -
How to interrupt function execution after X seconds?
helices replied to helices's topic in PHP Coding Help
Suffice it to say that the 10,000 line script works 100% - except that sometimes (1 in 500 runs) that line of code hangs for >30 minutes I've been coding for more than 40 years and PHP for more than 10 years. My code works. The rare hangs are not due to faulty code; rather, they are due to system problems, mostly on remote systems, over which I have 0 control All I am asking for is an example of a multi-tasked timer that can be set immediately prior to the function/subroutine call that includes: proc_open() - so that after X time, I can do something else, other than what that proc_open() is doing. Since "my" code includes PCI related security routines and the bulk of this has zero to do with this particular challenge, I will not be be posting: "ALL of your code" Is this too difficult for you? If so, please, accept my humblest apologies ... ~ Mike -
How to interrupt function execution after X seconds?
helices replied to helices's topic in PHP Coding Help
As I posted, this IS my code: $proc = proc_open($prog, $fd, $pipes, $ldir, null); One specific case, $prog is an lftp session to a remote server, getting or putting files Sometimes, unknown problem on that remote server leave this proc_open() call hanging. In these cases, I want an alarm-like process to do something after (30) minutes, such as write a message to STDERR and exit the script. What else do you need to know? -
How to interrupt function execution after X seconds?
helices replied to helices's topic in PHP Coding Help
It's your first: "waiting on an external process to complete" This works, but sometimes exceeds (30) minutes: $proc = proc_open($prog, $fd, $pipes, $ldir, null); I have a test script using: pcntl_alarm($time); before this: while ( $count < $max ) { ... } which works as desired It took me too long to realize that I needed to proceed pcntl_alarm() with this: declare(ticks=1); or it does not work :-( Does pcntl_alarm() require ticks? Why isn't this documented on the pcntl_alarm() manual page? When I do the $proc = ... thing - even with ticks - the alarm is never caught In the shell or even Perl, alarms work as I expect. What am I missing? -
I execute a system call via proc_open() that usually completes in less than one minute Sometimes, it hangs for many hours I want to exit this parent script after thirty (30) minutes with the error description on STDERR and I also want that system call process killed at this point Although, a test script using ticks and pcntl_alarm(1800) works using a while() loop, this does NOT work with my production system call Since ticks is documented as deprecated, I want to find a solution that does not use ticks What am I missing? Please, advise. Thank you ~ Mike