Comments (21)
最近看了很多EventLoop库,包括muduo,其实打多数库存在的问题是回调陷阱,就是回调发生期间,所依赖的对象已经被销毁的情况,导致段错误等问题,muduo这个问题会更加严重,uv-cpp至少能够在close的回调中delete掉对象,,muduo大部分情况下不知道在什么时候去销毁对象,可能在你刚销毁后,就遇到了捆绑此对象的回调,导致段错误。。
我觉得一个好的方法是全面使用智能指针,使用shared_ptr阻止其在回调没有执行前不能销毁,或者使用weak_ptr判断对象如果已经销毁了就不执行回调。
另外就是使用qt或者sigc这种信号和槽的机制,关注对象的生命周期,如果绑定的对象被销毁了,那么他就不会再去执行对应的回调了
这可能是最影响各种库稳定性的问题,还是那个最基本的问题,析构函数并没有清理掉所有相关联的资源,包括其他对象对这个对象的依赖。
from uv-cpp.
我尝试过,直接用runinthisloop,去执行async_->close,和uv_stop(handle),但是产生一个问题,eventloop中的async_的uv handle_是只能在之后的事件循环中被回调delete,像这样
::uv_close((uv_handle_t*)handle_, [](uv_handle_t* handle)
{
delete (uv_async_t*)handle;
});
但是loop在当前循环中已经被停止了,所以这个回调不能被调用,导致最终的内存泄漏,我觉得async 中的handle_的销毁应该交给async的析构,而不应当在事件回调中
from uv-cpp.
类似signal也是一样,只能主动调用close,并且当前的eventloop是正常执行的。
from uv-cpp.
@x724172556
在析构里面释放也会有问题。句柄必须在回调中释放。
所以这是我下一个版本要考虑的问题。
因为我自己使用Loop没有释放的需求,正常的程序里面也不会频繁创建Loop(想想只有动态扩展线程池才有这个需求)。
后面看看怎么弄比较安全,会解决这个问题。
from uv-cpp.
我想到了一个方法,但没有尝试过,就是eventloop添加一个接口,close(callback),我们在callback回调中执行关闭其他句柄的操作,例如tcpserver,此时uv_loop是已经停止了,下一次是无法进入循环的,真正的关闭句柄操作是无法执行的,那么我们再启动一次uv_loop,这次试用uv_run(onces),这样他就只执行一次循环就退出了,这个方法是否可行
from uv-cpp.
或者是在,callback执行以后,请求一个异步的关闭操作,在下个循环执行uv_stop
from uv-cpp.
void EventLoop2::stop(StopCallback callback)
{
runInThisLoop([this,callback](){
callback();
async_->close(nullptr);
uv_stop(handle());
});
}实际发现这样写,就能结束循环,并且能将 async_的uv句柄释放掉,只需要保证在uv_stop之前关闭掉其他句柄就可以了
from uv-cpp.
计划10.1更。
from uv-cpp.
v1.5.1 版本,增加eventloop退出机制,windows下测试无内存泄漏。例程:https://github.com/wlgq2/uv-cpp/tree/master/examples/loop_exit
from uv-cpp.
增加server退出机制。
from uv-cpp.
@x724172556 因为uv-cpp无法控制libuv不对一个析构对象的调用。接口最初设计成这样是为了向libuv妥协。后面看看有没有更好的办法。
from uv-cpp.
将需要回调的对象(tcpclient)继承object,然后object会将自身注册进eventloop,析构的时候注销,回调的话,就可以判断对象的生命周期,存活就回调。。。这是传统c++面对对象的事件框架机制,我不知道你对这种方案是否认同
from uv-cpp.
其实自己在对象外面包一层,析构里面Close,回调删对象,也不用手动调Close,直接删对象就行。参考HttpClient中删TcpClient。
https://github.com/wlgq2/uv-cpp/blob/master/uv/http/HttpClient.cpp
HttpClient::~HttpClient()
{
client_->close([](uv::TcpClient* client)
{
delete client;
});
}
from uv-cpp.
@x724172556 问题是,回调是从libuv中触发,我无法把智能指针保存到libuv里面不被析构。还有一个问题,就算智能指针保证了C++的析构后的对象不被调用。但是不能维护libuv自己指针的生命周期,比如在libuv自己loop未结束时,智能指针删除了某个libuv的句柄。程序core。
如果你觉得可行,可以尝试提交个dome,或者pr试试。
from uv-cpp.
给libuv的相关句柄在做一个 封装,这个封装不对外接口暴露,只是内部对象析构的调用这个句柄close,然后删句柄就行。有时间改改看。
from uv-cpp.
对,我的其中一个想法就是,析构函数应该执行一次close,因为我不知道libuv的close设置为null还会不会依赖uv_handle,所以我让他在所有的libuv的回调中先判断对象是否存活
from uv-cpp.
httpclient也是一个挺好的方法,把原来的tcpclient隐藏,作为一个内部类
from uv-cpp.
唯一的问题可能就是,如果eventloop stop之后,再析构,可能会导致close回调不会调用,导致内存泄漏
from uv-cpp.
你看runInLoop实现,如果当前loop是被停止的,是直接在调用线程中运行回调的。如果是loop没开始,则等待开始后在loop中回调。
from uv-cpp.
那应该没有问题
from uv-cpp.
我的解决思路如下所述,不过实际代码感觉很烂,需要的话可以提交
解决死亡之吻(对象实例销毁后,如果之前提交了很多回调,会回调进入函数代码,由于对象已经销毁,将造成内存访问异常,发生崩溃)
主要步骤:
一是在上述实例(母体)中new一个that类(子体)(that对应this),并在子体中记录母体对象(body->this),在母体回调函数中根据该that对象,判断body(实体)是否已经销毁了,采取相应的动作
二是在母体中加上一个门卫(std::recursive_mutex),母体析构函数和回调函数通过该门卫同步执行代码,避免析构后,多线程同时操作造成崩溃,该门卫可以放入步骤一中的that类合并实现,注意不能用std::mutex(有可能产生递归加锁)
三是母体析构函数中如果一时处理不完,有后续动作,可在that类中加入回调功能,在母体中设置一个回调函数,在该函数中可以做一些善后工作(说明:函数代码不会随对象销毁而销毁,该代码中不能处理已经销毁/释放的数据)
from uv-cpp.
Related Issues (20)
- uv::Packet::readFromBuffer 的解包问题? HOT 3
- new EventLoop,再delete,VS报告内存泄露 HOT 1
- packet中size为uint16_t存放数据长度是否太小? HOT 2
- 新版的代码中有未定义的 ssize_t
- 编译出错 HOT 2
- TimerWheel 类的是否会将没有超时连接删除 HOT 8
- 请问是否支持ssl? HOT 1
- 关于内存的释放问题 HOT 5
- httpserver长链接
- uv-cpp做客户端时,当服务端连不上,重复去连接时,无论是linux还是Windows都会奔溃 HOT 14
- libuv升级到新版本支持吗 HOT 1
- client跨线程循环发送时候 ,client崩溃 HOT 4
- linux centos7下,偶现程序运行一段时间后,CPU使用率100%的情况。最后奔溃。 HOT 1
- centos 7 运行一晚第二天看到崩溃了 HOT 2
- 请教下 这个可以支持百万或者千万并发吗? HOT 3
- 你好,cmake和make之后该怎么运行helloworld例子 HOT 3
- async 有对应的例子吗?
- http中增加一个 http 添加 静态文件目录 ? HOT 1
- 有没有多线程或者线程池的例子,如何开16个线程
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from uv-cpp.