Skip to content

Commit f7f1301

Browse files
Merge pull request #4774 from nextcloud/backport/4746/stable20
[stable20] Use proc_open to run system commands in bridge manager
2 parents 55ca503 + 43bc4b9 commit f7f1301

File tree

1 file changed

+61
-20
lines changed

1 file changed

+61
-20
lines changed

lib/MatterbridgeManager.php

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -663,16 +663,15 @@ private function sendSystemMessage(Room $room, string $userId, string $message):
663663
*/
664664
private function launchMatterbridge(Room $room): int {
665665
$binaryPath = $this->config->getAppValue('spreed', 'matterbridge_binary');
666-
// TODO this should be in appdata
667666
$configPath = sprintf('/tmp/bridge-%s.toml', $room->getToken());
668667
$outputPath = sprintf('/tmp/bridge-%s.log', $room->getToken());
669-
$cmd = sprintf('%s -conf %s', $binaryPath, $configPath);
670-
$pid = exec(sprintf('nice -n19 %s > %s 2>&1 & echo $!', $cmd, $outputPath), $output, $ret);
671-
$pid = (int) $pid;
672-
if ($ret !== 0) {
673-
$pid = 0;
668+
$matterbridgeCmd = sprintf('%s -conf %s', $binaryPath, $configPath);
669+
$cmd = sprintf('nice -n19 %s > %s 2>&1 & echo $!', $matterbridgeCmd, $outputPath);
670+
$cmdResult = $this->runCommand($cmd);
671+
if (!is_null($cmdResult) && $cmdResult['return_code'] === 0 && is_numeric($cmdResult['stdout'] ?? 0)) {
672+
return (int) $cmdResult['stdout'];
674673
}
675-
return $pid;
674+
return 0;
676675
}
677676

678677
/**
@@ -681,11 +680,19 @@ private function launchMatterbridge(Room $room): int {
681680
*/
682681
public function killZombieBridges(bool $killAll = false): void {
683682
// get list of running matterbridge processes
684-
$cmd = 'ps x -o user,pid,args | grep "matterbridge" | grep -v grep | awk \'{print $2}\'';
685-
exec($cmd, $output, $ret);
686683
$runningPidList = [];
687-
foreach ($output as $o) {
688-
$runningPidList[] = (int) $o;
684+
$cmd = 'ps x -o user,pid,args';
685+
$cmdResult = $this->runCommand($cmd);
686+
if ($cmdResult && $cmdResult['return_code'] === 0) {
687+
$lines = explode("\n", $cmdResult['stdout']);
688+
foreach ($lines as $l) {
689+
if (preg_match('/matterbridge/i', $l)) {
690+
$items = preg_split('/\s+/', $l);
691+
if (count($items) > 1 && is_numeric($items[1])) {
692+
$runningPidList[] = (int) $items[1];
693+
}
694+
}
695+
}
689696
}
690697

691698
if (empty($runningPidList)) {
@@ -729,10 +736,11 @@ public function killZombieBridges(bool $killAll = false): void {
729736
*/
730737
private function killPid(int $pid): bool {
731738
// kill
732-
exec(sprintf('kill -9 %d', $pid), $output, $ret);
739+
$cmdResult = $this->runCommand(sprintf('kill -9 %d', $pid));
740+
733741
// check the process is gone
734742
$isStillRunning = $this->isRunning($pid);
735-
return (int) $ret === 0 && !$isStillRunning;
743+
return !is_null($cmdResult) && $cmdResult['return_code'] === 0 && !$isStillRunning;
736744
}
737745

738746
/**
@@ -743,15 +751,49 @@ private function killPid(int $pid): bool {
743751
*/
744752
private function isRunning(int $pid): bool {
745753
try {
746-
$result = shell_exec(sprintf('ps x -o user,pid,args | awk \'{print $2}\' | grep "^%d$" | wc -l', $pid));
747-
if ((int) $result > 0) {
748-
return true;
754+
$cmd = 'ps x -o user,pid,args';
755+
$cmdResult = $this->runCommand($cmd);
756+
if ($cmdResult && $cmdResult['return_code'] === 0) {
757+
$lines = explode("\n", $cmdResult['stdout']);
758+
foreach ($lines as $l) {
759+
$items = preg_split('/\s+/', $l);
760+
if (count($items) > 1 && is_numeric($items[1])) {
761+
$lPid = (int) $items[1];
762+
if ($lPid === $pid) {
763+
return true;
764+
}
765+
}
766+
}
749767
}
750768
} catch (\Exception $e) {
751769
}
752770
return false;
753771
}
754772

773+
/**
774+
* Launch a command, wait until it ends and return outputs and return code
775+
*
776+
* @param string $cmd command string
777+
* @return ?array outputs and return code, null if process launch failed
778+
*/
779+
private function runCommand(string $cmd): ?array {
780+
$descriptorspec = [fopen('php://stdin', 'r'), ['pipe', 'w'], ['pipe', 'w']];
781+
$process = proc_open($cmd, $descriptorspec, $pipes);
782+
if ($process) {
783+
$output = stream_get_contents($pipes[1]);
784+
$errorOutput = stream_get_contents($pipes[2]);
785+
fclose($pipes[1]);
786+
fclose($pipes[2]);
787+
$returnCode = proc_close($process);
788+
return [
789+
'stdout' => trim($output),
790+
'stderr' => trim($errorOutput),
791+
'return_code' => $returnCode,
792+
];
793+
}
794+
return null;
795+
}
796+
755797
/**
756798
* Stop all bridges
757799
*
@@ -871,12 +913,11 @@ public function getCurrentVersionFromBinary(): ?string {
871913
}
872914

873915
$cmd = escapeshellcmd($binaryPath) . ' ' . escapeshellarg('-version');
874-
@exec($cmd, $output, $returnCode);
875-
876-
if ($returnCode !== 0) {
916+
$cmdResult = $this->runCommand($cmd);
917+
if (is_null($cmdResult) || $cmdResult['return_code'] !== 0) {
877918
return null;
878919
}
879920

880-
return trim(implode("\n", $output));
921+
return $cmdResult['stdout'] ?? null;
881922
}
882923
}

0 commit comments

Comments
 (0)