Skip to content

Commit 00072f9

Browse files
committed
Add noCleanup parameter to improve process timeout handling in SSH operations
1 parent 927c9ef commit 00072f9

2 files changed

Lines changed: 22 additions & 4 deletions

File tree

src/Ssh/RunParams.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public function __construct(
1111
public ?string $dotenv = null,
1212
public bool $nothrow = false,
1313
public ?int $timeout = null,
14+
public bool $noCleanup = false,
1415
public ?int $idleTimeout = null,
1516
public bool $forceOutput = false,
1617
#[\SensitiveParameter]
@@ -21,10 +22,12 @@ public function with(
2122
#[\SensitiveParameter]
2223
?array $secrets = null,
2324
?int $timeout = null,
25+
?bool $noCleanup = null,
2426
): self {
2527
$params = clone $this;
2628
$params->secrets = array_merge($params->secrets ?? [], $secrets ?? []);
2729
$params->timeout = $timeout ?? $params->timeout;
30+
$params->noCleanup = $noCleanup ?? $params->noCleanup;
2831
return $params;
2932
}
3033
}

src/Ssh/SshClient.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public function run(Host $host, string $command, RunParams $params): string
4646
if ($this->output->isDebug()) {
4747
$sshString = $ssh[0];
4848
for ($i = 1; $i < count($ssh); $i++) {
49-
$sshString .= ' ' . \Deployer\quote((string) $ssh[$i]);
49+
$sshString .= ' ' . \Deployer\quote((string)$ssh[$i]);
5050
}
5151
$this->output->writeln("[$host] $sshString");
5252
}
@@ -76,9 +76,24 @@ public function run(Host $host, string $command, RunParams $params): string
7676
$process->run($callback);
7777
} catch (ProcessTimedOutException $exception) {
7878
// Let's try to kill all processes started by this command.
79-
$pid = $this->run($host, "ps x | grep $shellId | grep -v grep | awk '{print \$1}'", $params->with(timeout: 10));
80-
// Minus before pid means all processes in this group.
81-
$this->run($host, "kill -9 -$pid", $params->with(timeout: 20));
79+
// Cleanup runs pass noCleanup so a timeout here can't recurse,
80+
// and cleanup failures must not mask the timeout, so swallow them.
81+
if (!$params->noCleanup) {
82+
try {
83+
$pid = trim($this->run(
84+
$host,
85+
"ps x | grep $shellId | grep -v grep | awk '{print \$1}'",
86+
$params->with(timeout: 10, noCleanup: true),
87+
));
88+
if ($pid !== '') {
89+
// Minus before pid means all processes in this group.
90+
$this->run($host, "kill -9 -$pid", $params->with(timeout: 20, noCleanup: true));
91+
}
92+
} catch (\Throwable) {
93+
// The shell may have already exited, or `ps`/`kill` may be
94+
// restricted. Either way, the timeout is the real error.
95+
}
96+
}
8297
throw new TimeoutException(
8398
$command,
8499
$exception->getExceededTimeout(),

0 commit comments

Comments
 (0)