execWithTimeout() closes all pipes and also returns return value of cmd

This commit is contained in:
Uwe Steinmann 2021-05-10 08:54:18 +02:00
parent c37802fdca
commit 4f59c3b4e8
4 changed files with 45 additions and 6 deletions

View File

@ -40,9 +40,11 @@ class SeedDMS_Lucene_IndexedDocument extends Zend_Search_Lucene_Document {
protected $cmd;
/**
* Run a shell command
*
* @param $cmd
* @param int $timeout
* @return string
* @return array
* @throws Exception
*/
static function execWithTimeout($cmd, $timeout=2) { /* {{{ */
@ -54,7 +56,11 @@ class SeedDMS_Lucene_IndexedDocument extends Zend_Search_Lucene_Document {
$pipes = array();
$timeout += time();
$process = proc_open($cmd, $descriptorspec, $pipes);
// Putting an 'exec' before the command will not fork the command
// and therefore not create any child process. proc_terminate will
// then reliably terminate the cmd and not just shell. See notes of
// https://www.php.net/manual/de/function.proc-terminate.php
$process = proc_open('exec '.$cmd, $descriptorspec, $pipes);
if (!is_resource($process)) {
throw new Exception("proc_open failed on: " . $cmd);
}
@ -79,11 +85,15 @@ class SeedDMS_Lucene_IndexedDocument extends Zend_Search_Lucene_Document {
$timeleft = $timeout - time();
} while (!feof($pipes[1]) && $timeleft > 0);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
if ($timeleft <= 0) {
proc_terminate($process);
throw new Exception("command timeout on: " . $cmd);
} else {
return array('stdout'=>$output, 'stderr'=>$error);
$return_value = proc_close($process);
return array('stdout'=>$output, 'stderr'=>$error, 'return'=>$return_value);
}
} /* }}} */

View File

@ -70,6 +70,14 @@ class SeedDMS_Preview_Base {
$this->xsendfile = $xsendfile;
} /* }}} */
/**
* Run a shell command
*
* @param $cmd
* @param int $timeout
* @return array
* @throws Exception
*/
static function execWithTimeout($cmd, $timeout=5) { /* {{{ */
$descriptorspec = array(
0 => array("pipe", "r"),
@ -108,11 +116,15 @@ class SeedDMS_Preview_Base {
$timeleft = $timeout - time();
} while (!feof($pipes[1]) && $timeleft > 0);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
if ($timeleft <= 0) {
proc_terminate($process);
throw new Exception("command timeout on: " . $cmd);
} else {
return array('stdout'=>$output, 'stderr'=>$error);
$return_value = proc_close($process);
return array('stdout'=>$output, 'stderr'=>$error, 'return'=>$return_value);
}
} /* }}} */

View File

@ -128,6 +128,7 @@ class SeedDMS_Preview_Previewer extends SeedDMS_Preview_Base {
}
return true;
}
$new = false;
return true;
} /* }}} */

View File

@ -44,6 +44,14 @@ class SeedDMS_SQLiteFTS_IndexedDocument extends SeedDMS_SQLiteFTS_Document {
*/
protected $cmd;
/**
* Run a shell command
*
* @param $cmd
* @param int $timeout
* @return array
* @throws Exception
*/
static function execWithTimeout($cmd, $timeout=2) { /* {{{ */
$descriptorspec = array(
0 => array("pipe", "r"),
@ -53,7 +61,11 @@ class SeedDMS_SQLiteFTS_IndexedDocument extends SeedDMS_SQLiteFTS_Document {
$pipes = array();
$timeout += time();
$process = proc_open($cmd, $descriptorspec, $pipes);
// Putting an 'exec' before the command will not fork the command
// and therefore not create any child process. proc_terminate will
// then reliably terminate the cmd and not just shell. See notes of
// https://www.php.net/manual/de/function.proc-terminate.php
$process = proc_open('exec '.$cmd, $descriptorspec, $pipes);
if (!is_resource($process)) {
throw new Exception("proc_open failed on: " . $cmd);
}
@ -78,11 +90,15 @@ class SeedDMS_SQLiteFTS_IndexedDocument extends SeedDMS_SQLiteFTS_Document {
$timeleft = $timeout - time();
} while (!feof($pipes[1]) && $timeleft > 0);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
if ($timeleft <= 0) {
proc_terminate($process);
throw new Exception("command timeout on: " . $cmd);
} else {
return array('stdout'=>$output, 'stderr'=>$error);
$return_value = proc_close($process);
return array('stdout'=>$output, 'stderr'=>$error, 'return'=>$return_value);
}
} /* }}} */