span.cpp中destroy()方法存在内存重复释放问题,会导致服务崩掉
Describe the bug 服务开启enable_rpcz后,上线跑一段时间就会内存暴涨然后core掉,经排查定位发现在destroy()中存在内存重复释放问题。
void Span::destroy() {
EndAsParent();
Span* p = _next_client;
while (p) {
if (p == this) {
LOG(ERROR) << "Span next_client points to self, span_id=" << p->_span_id;
}
Span* p_next = p->_next_client;
p->_info.clear();
butil::return_object(p);
p = p_next;
}
_info.clear();
butil::return_object(this);
}
如上代码,ERROR日志是我debug时加的,经过验证在服务core掉时确实打印了该行日志。 说明span链表中有span异常指向了自身。
这个问题的根源是什么?新版本是否有解决该问题?
To Reproduce
Expected behavior
Versions OS: centos7.6 Compiler: gcc4.8.5 brpc: 0.9.0 protobuf:
Additional context/screenshots
新版本的代码有修改,不过span的使用也是需要注意一下的。你的使用场景是怎么样的?会启动bthread,并发操作span吗?
新版本的代码有修改,不过span的使用也是需要注意一下的。你的使用场景是怎么样的?会启动bthread,并发操作span吗?
服务调用时会并发请求,比如我们出现core的服务是a,服务a内部调用a->b,a->c,a->d,三次请求是并发的,未显示使用bthread,用的是brpc异步请求。 这种使用方式会有问题吗?
新版本的代码有修改,不过span的使用也是需要注意一下的。你的使用场景是怎么样的?会启动bthread,并发操作span吗?
服务调用时会并发请求,比如我们出现core的服务是a,服务a内部调用a->b,a->c,a->d,三次请求是并发的,未显示使用bthread,用的是brpc异步请求。 这种使用方式会有问题吗?
按说异步RPC也没问题,只是b、c、d必须保证在a之前结束。
新版本的代码有修改,不过span的使用也是需要注意一下的。你的使用场景是怎么样的?会启动bthread,并发操作span吗?
服务调用时会并发请求,比如我们出现core的服务是a,服务a内部调用a->b,a->c,a->d,三次请求是并发的,未显示使用bthread,用的是brpc异步请求。 这种使用方式会有问题吗?
按说异步RPC也没问题,只是b、c、d必须保证在a之前结束。
是的,b、c、d肯定是保证在a之前返回的
按说异步RPC也没问题,只是b、c、d必须保证在a之前结束。
是的,b、c、d肯定是保证在a之前返回的
比较常见的case是,a 的回调中发起 异步rpc b c d 之后没有 join b c d, 而是调用了 run->done, 在 run -> done 中会认为所有的 sub rpc 已经完成并 destroy span, 从而导致 b c d完成之后操作 dangling pointer 可以check下代码里有没有这种case