fix(openflare): refresh WS read deadline on JSON pong; capture frpc stderr

- read_pump: 收到客户端 JSON {"type":"pong"} 时调用 conn.SetReadDeadline 刷新
  服务端读超时。修复前,服务端仅在 WebSocket 协议层 Pong 帧时刷新 deadline,
  而客户端使用 JSON 应用层 pong 回复,导致服务端 90s 后超时关闭连接,
  客户端收到 EOF 并触发无限重连循环。在 Cloudflare 代理场景下,
  100s 空闲超时进一步加剧了此问题。

- frpc/manager: 捕获 frpc 子进程 stderr 并在进程异常退出时
  将其内容记录到结构化日志 stderr 字段,便于诊断 exit status 1 的
  具体原因(如配置格式错误、Auth Token 失败、relay 服务端不可达等)。
This commit is contained in:
ryan
2026-06-22 14:22:20 +08:00
parent 346024f346
commit 1e5f35b9a3
2 changed files with 15 additions and 1 deletions
+8 -1
View File
@@ -192,6 +192,8 @@ func (m *Manager) restartProcess(ctx context.Context, relayID string, configPath
ensureNoOrphanProcess(pidPath)
cmd := exec.CommandContext(procCtx, m.cfg.FrpcPath, "-c", configPath) //nolint:gosec // FrpcPath and configPath are managed trusted locations
var stderrBuf bytes.Buffer
cmd.Stderr = &stderrBuf
m.mu.Lock()
proc.Cmd = cmd
@@ -213,10 +215,15 @@ func (m *Manager) restartProcess(ctx context.Context, relayID string, configPath
return
}
stderrOutput := strings.TrimSpace(stderrBuf.String())
if err != nil {
proc.LastError = err.Error()
proc.Status = "error"
slog.Error("frpc process exited unexpectedly", "relay_id", relayID, "error", err)
if stderrOutput != "" {
slog.Error("frpc process exited unexpectedly", "relay_id", relayID, "error", err, "stderr", stderrOutput)
} else {
slog.Error("frpc process exited unexpectedly", "relay_id", relayID, "error", err)
}
} else {
proc.Status = "stopped"
proc.LastError = "exited unexpectedly with code 0"