Handle game process exit gracefully

- Added proc_get_status() check in readProcessOutput() to detect when
  the game process has exited
- When process exits, read any remaining output and send to client
- Send system message to notify client that game process has ended
- Close client connection cleanly when process exits
- Prevents server from trying to read/write to dead process pipes
- Prevents "broken pipe" errors and connection hangs

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
hant 2025-12-07 14:53:06 +08:00
parent 7c103d7209
commit 73f1d4ba9d

View File

@ -181,11 +181,56 @@ class GameProcessServer implements MessageComponentInterface
*/ */
private function readProcessOutput(ConnectionInterface $conn): void private function readProcessOutput(ConnectionInterface $conn): void
{ {
$process = $this->processes[$conn->resourceId] ?? null; $connId = $conn->resourceId;
$process = $this->processes[$connId] ?? null;
if (!$process) { if (!$process) {
return; return;
} }
// 检查进程是否还在运行
$processStatus = proc_get_status($process['process']);
if ($processStatus && !$processStatus['running']) {
// 进程已经退出,读取最后的输出并关闭连接
echo "[进程] 进程 {$connId} 已退出,状态码: " . $processStatus['exitcode'] . "\n";
// 尝试读取任何剩余的输出
$finalOutput = '';
$bufferSize = 8192;
while (true) {
$chunk = @fread($process['stdout'], $bufferSize);
if ($chunk === '' || $chunk === false) {
break;
}
$finalOutput .= $chunk;
}
while (true) {
$chunk = @fread($process['stderr'], $bufferSize);
if ($chunk === '' || $chunk === false) {
break;
}
$finalOutput .= $chunk;
}
if ($finalOutput) {
$this->sendMessage($conn, [
'type' => 'output',
'text' => $finalOutput
]);
}
// 发送进程退出消息
$this->sendMessage($conn, [
'type' => 'system',
'message' => '游戏进程已退出'
]);
// 关闭连接
$conn->close();
return;
}
$output = ''; $output = '';
// 在非阻塞模式下使用fread读取可用数据 // 在非阻塞模式下使用fread读取可用数据