Skip to content

Commit 5c2e0ab

Browse files
somethingwithproofTheWitnessCopilot
authored
[1.2.x] fix: exec_with_timeout operator precedence, child kill, and stderr handling (Cacti#6732)
* fix: backport exec_with_timeout operator precedence, child kill, and stderr handling - Fix operator precedence: `(int)` cast bound tighter than multiplication, so timeout never decreased. Parenthesise the float expression first. - Kill entire process group via posix_kill(-pid, 9) before proc_terminate to prevent orphaned child processes when timeout expires. - Log stderr as POLLER warning instead of discarding valid stdout output by returning false. Backport of fixes from develop branch fix/exec-with-timeout-bugs. Addresses issues Cacti#6719, Cacti#6720, Cacti#6721. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix: use setsid for correct process group kill on timeout Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix: avoid process-group kill in exec_with_timeout Use direct PID kill to avoid targeting unrelated process groups. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix: clarify exec_with_timeout kill semantics Document why direct PID kill is used instead of process-group signaling. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> Co-authored-by: TheWitness <thewitness@cacti.net> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent b514026 commit 5c2e0ab

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

lib/poller.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ function exec_with_timeout($cmd, &$output, &$return_code, $timeout = 5) {
179179
);
180180

181181
// Start the process.
182-
$process = proc_open('exec ' . $cmd, $descriptors, $pipes);
182+
$process = proc_open('exec setsid ' . $cmd, $descriptors, $pipes);
183183

184184
if (!is_resource($process)) {
185185
return false;
@@ -222,7 +222,7 @@ function exec_with_timeout($cmd, &$output, &$return_code, $timeout = 5) {
222222
}
223223

224224
// Subtract the number of microseconds that we waited.
225-
$timeout -= (int) (microtime(true) - $start) * 1000000;
225+
$timeout -= (int) ((microtime(true) - $start) * 1000000);
226226
}
227227

228228
// Check if there were any errors.
@@ -235,11 +235,17 @@ function exec_with_timeout($cmd, &$output, &$return_code, $timeout = 5) {
235235
}
236236

237237
if (!empty($errors)) {
238-
return false;
238+
cacti_log('WARNING: exec_with_timeout stderr: ' . trim($errors), false, 'POLLER', POLLER_VERBOSITY_MEDIUM);
239239
}
240240

241241
// Kill the process in case the timeout expired and it's still running.
242242
// If the process already exited this won't do anything.
243+
// Do not use a negative PID here because the child PID is not guaranteed
244+
// to be the process-group ID on every platform/runtime combination.
245+
if (isset($status['pid']) && $status['running'] && function_exists('posix_kill')) {
246+
posix_kill($status['pid'], 9);
247+
}
248+
243249
proc_terminate($process, 9);
244250

245251
// Close all streams.

0 commit comments

Comments
 (0)