-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Description
Describe the bug
在服务端处理带 stream 的 RPC 时,如果 handler 中调用了 brpc::StreamAccept(),但在 brpc 发送 RPC response 并绑定 stream 到 host socket 之前,对端连接刚好断开,那么
Socket::AddStream() 会返回失败,随后 Stream::SetHostSocket() 触发 CHECK(false),直接导致进程 abort。
相关调用链:
SendRpcResponse() -> Stream::SetHostSocket() -> Socket::AddStream() -> CHECK(false)
fatal 日志类似:
stream.cpp:648 Check failed: false <stream_id> fail to add stream to host socket
To Reproduce
一个通用场景如下:
- 服务端收到一个带 remote stream 的请求
- handler 中调用
brpc::StreamAccept(...) - handler 正常返回
- 在
StreamAccept()成功之后、SendRpcResponse()执行之前,对端关闭连接或底层 TCP reset - 服务端在
Stream::SetHostSocket()中崩溃
最小化代码形态大致如下:
void Foo(::google::protobuf::RpcController* controller,
const Request* req,
Response* res,
::google::protobuf::Closure* done) {
brpc::ClosureGuard done_guard(done);
auto* cntl = static_cast<brpc::Controller*>(controller);
brpc::StreamId stream_id;
brpc::StreamOptions opt;
opt.handler = &handler;
if (brpc::StreamAccept(&stream_id, *cntl, &opt) != 0) {
cntl->SetFailed("StreamAccept failed");
return;
}
res->set_ok(true);
}这个问题更容易在网络抖动、连接被主动 reset、或者对端反复重连时触发。
Expected behavior
这类情况应该被当作一个可恢复的连接失败处理:
- 当前 stream / 当前 RPC 失败
- 服务端进程继续运行
而不是因为 CHECK(false) 直接崩溃整个进程。
Versions
OS: Rocky 9.6
Compiler: g++ (GCC) 12.2.1
brpc: 1.16
protobuf:
Additional context/screenshots
从源码看,Socket::AddStream() 在 socket 已 failed 时返回 -1,这更像是一个运行期边界条件,而不是必须用 CHECK(false) 处理的“不可能事件”。
想确认一下,社区是否接受把这里改为普通错误返回/失败清理,而不是直接 abort?