Skip to content

多个TcpClient/UdpClient共用一个EventLoop,析构时有概率崩溃 #704

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
hello-Li-sir opened this issue Apr 1, 2025 · 8 comments

Comments

@hello-Li-sir
Copy link

Image
Image

@ithewei
Copy link
Owner

ithewei commented Apr 1, 2025

退出线程时应该等待IO线程结束,return 0前,加

loopThread.stop();
loopThread.join();

试试

@hello-Li-sir
Copy link
Author

hello-Li-sir commented Apr 1, 2025 via email

@ithewei
Copy link
Owner

ithewei commented Apr 1, 2025

最新master分支上有个修复,看看带上没41c63bf

@hello-Li-sir
Copy link
Author

hello-Li-sir commented Apr 1, 2025 via email

@House-Men
Copy link
Contributor

原因是执行启动的时候 loop_->runInLoop(std::bind(&UdpClientEventLoopTmpl::startRecv, this)); 这个是投递启动事件到loop线程异步触发启动,而startRecv还没来得及执行你的UdpClient对象就析构了,导致后续startRecv启动后使用的this指针父类Channel相关内存数据全部无效从而崩溃。

而不使用外部loop时不存在此现象是因为is_loop_owner=true的内部线程stop时会执行终止线程。

要解决这个问题就必须作者想个好办法优化stop逻辑,我发现许多cpp封装对象涉及异步事件执行的地方都可能因this对象析构从而产生崩溃潜在问题,临时解决方案就是调用start之后检测hio的事件是否不等于0来判断异步触发启动完成可以执行后续停止或析构,我在你的代码示例基础增加 while (hio_events(client1.channel->io()) == 0) std::this_thread::yield(); 即可避免崩溃。

@ithewei @hello-Li-sir

Image

@hello-Li-sir
Copy link
Author

hello-Li-sir commented Apr 2, 2025 via email

@House-Men
Copy link
Contributor

House-Men commented Apr 2, 2025

析构会崩问题同源,就像之前那个onClose析构后触发会崩溃的优化提交和你这个例子会析构后触发startRecv崩溃,本质上都是同一个原因,只要用到外部loop内部的停止逻辑都不会等待终止线程,所以你只要出现析构后loop触发了什么事件回调在回调处理中又用到被释放的对象成员数据就会崩溃。但并不是百分百触发,有时候会因为运行环境的不同对象释放后内存被填充成0导致某些异步回调触发判断是否为空条件成立从而避免崩溃。

@ithewei
Copy link
Owner

ithewei commented Apr 2, 2025

是的,这种方式必须十分小心TcpClient/UdpClient的生命周期,最好的实践是使用堆对象,然后调用loop->runInLoop{delete cli;}在事件循环所在线程里删除对象,参考这个示例程序
https://github.com/ithewei/libhv/blob/master/evpp/TcpClientEventLoop_test.cpp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants