Hardcoded 5 second timeout for writing pong response can cause errors
- 主要语言
- Go
- 星标
- 5.5k
- 派生
- 372
- PR 合并指标
- 30 天内没有已合并 PR
描述
An inbound ping has a hardcoded 5 second deadline to handle the incoming message and send out a pong response. The general codepath for such a scenario is:
`Conn.readLoop`->`h.opcode==opPing`->`handleControl(..., opPing)`->`writeControl(..., opPong)`
The two 5 second context-based timeouts declared here:
1. https://github.com/coder/websocket/blob/9f473adfa59519d1e0295cd7a988d965085b701a/read.go#L302
2. https://github.com/coder/websocket/blob/9f473adfa59519d1e0295cd7a988d965085b701a/write.go#L277
These timeouts can cause the Websocket connection to close with an unrecoverable error. I can go into more detail about the two possible situations that can cause this condition if required, but just note that the network connection is extremely poor both in reliability and speed, and the connection is generally busy sending data (chunked enough to allow the incoming ping frames to be handled for the average network speed assuming no interruptions).
```failed to get reader: failed to handle control frame opPing: failed to write control frame opPong: failed to acquire lock: context deadline exceeded```
The problem mostly arises when the connection is briefly interrupted or the write mutex is otherwise busy underneath an in-flight inbound ping message. This 5 second timeout is not enough to be able to write the pong response.
Proposals:
1. Allow this timeout value to be configurable - at the very least for ping/pong control frames.
2. Increase this hardcoded timeout to 20 seconds by default - perhaps only for ping/pong frames?
This is generally more in line with other implementations I've found that have a default value - though most do not have a default timeout at all and rely on the user to implement ping handling in their own way.
- https://websockets.readthedocs.io/en/stable/reference/asyncio/client.html#websockets.asyncio.client.connect - `open_timeout=10, ping_interval=20, ping_timeout=20, close_timeout=10`
- https://socket.io/docs/v4/server-options/#pingtimeout (granted this isn't a pure Websocket library)
Definitely open to other ideas, and I'm happy to get a PR up for this, but for now I've forked the repo to change this value.
贡献指南
这个仓库没有索引到贡献指南
调研方向
从 read.go 中 opPing 处理程序附近的入站 ping 流程,以及 write.go 中硬编码的五秒 context 附近的 pong 写入路径开始。复现或分析写入 mutex 被阻塞和连接中断的情况,然后决定 ping/pong 超时应如何工作。完成标准是:在报告的条件下连接不再提前失败,并且通过测试覆盖所选的默认值或配置。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- go
- 领域
- networking
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 冷清
- 描述清晰度
- 基本清楚
- 新手友好度
- 45/100