---
date: 2026-05-10
component: gitea-infrastructure
severity: blocker
recurrence: unknown
---

# Gitea HTTP hangs while TCP/SSH still accept connections

## 现象

`weekly-retro` skill (runner mode, ISO 周 2026-W19) 跑 `scripts/ops/weekly-review.py`，
脚本在拉 Gitea API 时 socket `recv` timeout，stack trace 顶到 `urllib.request.do_open`
→ `http.client.getresponse` → `_read_status` → `socket.recv_into`：

```
TimeoutError: timed out
```

直接用 `curl --max-time 20 http://43.130.59.228/api/v1/version` 复现：
- TCP connect 立刻成功（Connected to 43.130.59.228:80）
- 发完 GET 请求行 + Host 头之后，server 不返回任何字节，20 秒超时

## 探针结果

| 探针 | 结果 |
|---|---|
| `ping 43.130.59.228` | 0% loss, 0.78ms RTT |
| `/dev/tcp/43.130.59.228/80` | OK (TCP accept) |
| `/dev/tcp/43.130.59.228/443` | Connection refused（一向如此，HTTPS 没开） |
| `/dev/tcp/43.130.59.228/2222` | OK (SSH) |
| `curl http://.../api/v1/version` | hang 到超时，0 字节 |

**TCP 层正常，HTTP 层挂死** —— 典型表现：Gitea 进程或反向代理 hung，
socket accept 队列还在收，但 application thread 不消费请求 / 不返回响应。

## 根因（推测）

未登机排查，但模式上是以下之一：
1. Gitea Web 进程 deadlock / GC pause / 全部 worker 卡在某个慢查询
2. 反代（Nginx / Caddy）upstream 全挂，accept 后等 upstream 等到自身超时
3. 数据库连接池耗尽，HTTP handler 卡在 DB await

需要登机看 `pm2 logs gitea` / `docker logs <gitea-container>` / `systemctl status` 才能定。

## 影响

- `weekly-retro` runner 当周无法跑（决策树 Step 2 查 issue 失败）
- 任何依赖 Gitea API 的本地脚本都会卡（`gitea-pr-merge.py` / `weekly-review.py` 等）
- 浏览器访问 Gitea Web UI 应该也是白屏/转圈

## 对 weekly-retro skill 的处理

按 SKILL.md 的失败模式表，这种场景未明列（表里只有 token 缺失 / 403 / 5xx）。
HTTP 0 字节超时既不是 5xx 也不是 403，本质是 server 无响应。

runner mode 选择的策略：
- **不**创建/修改 issue（Step 2 都没法查，盲写会破坏 idempotency）
- 输出 `ERROR: gitea unreachable (HTTP hung at TCP-OK), retried 1x` 然后退出
- 落 ERR 文件（本文件）供后续 skill 升级参考

## 建议升级 SKILL.md（后续 PR）

`weekly-retro/SKILL.md` 失败模式表加一行：

| Gitea HTTP hang（TCP OK 但无响应） | 重试 1 次仍失败则退出，**绝不写 issue**（决策树前置依赖断了，写入会污染状态） |

## 临时绕行

人工排查（不在本 session 范围）：
1. SSH 到 Gitea host（`ssh git@43.130.59.228 -p 2222` 还能连），查 Gitea 进程
2. `docker logs` / `pm2 logs` 看是否有 deadlock / OOM / GC 信号
3. 重启 Gitea 服务（运维人工操作，AI 不直接执行生产变更）

恢复后重跑：
```bash
WEEKLY_RETRO_TOKEN=... bash scripts/ops/weekly-retro-runner.sh
# 或 Claude session 内 @weekly-retro
```
skill 的 idempotency 保证当周重跑不会重复创建 issue。

## 关联 learnings

- `2026-05-01-gitea-host-runner-oom.md`（Gitea host 资源问题历史）
- `2026-05-09-gitea-actions-runs-api-field-quirks.md`（Gitea API 行为）
