-
Notifications
You must be signed in to change notification settings - Fork 1.3k
多个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
Comments
退出线程时应该等待IO线程结束,return 0前,加
试试 |
没用,return 0之前加过死循环,IO线程没结束也会崩
…------------------ 原始邮件 ------------------
发件人: "ithewei/libhv" ***@***.***>;
发送时间: 2025年4月1日(星期二) 下午3:44
***@***.***>;
***@***.******@***.***>;
主题: Re: [ithewei/libhv] 多个TcpClient/UdpClient共用一个EventLoop,析构时有概率崩溃 (Issue #704)
退出线程时应该等待IO线程结束,return 0前,加一个loopThread.stop();试试
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you authored the thread.Message ID: ***@***.***>
ithewei left a comment (ithewei/libhv#704)
退出线程时应该等待IO线程结束,return 0前,加一个loopThread.stop();试试
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
最新master分支上有个修复,看看带上没41c63bf |
用的最新版本 还是有这个问题 window平台
…------------------ 原始邮件 ------------------
发件人: "ithewei/libhv" ***@***.***>;
发送时间: 2025年4月1日(星期二) 下午3:54
***@***.***>;
***@***.******@***.***>;
主题: Re: [ithewei/libhv] 多个TcpClient/UdpClient共用一个EventLoop,析构时有概率崩溃 (Issue #704)
最新master分支上有个修复,看看带上没41c63bf
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you authored the thread.Message ID: ***@***.***>
ithewei left a comment (ithewei/libhv#704)
最新master分支上有个修复,看看带上没41c63bf
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
原因是执行启动的时候 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(); 即可避免崩溃。 |
这个跟你分析的原因还不一样,我测试的时候执行完startRecv还是会崩。本身发现的这个问题时候Tcp就已经建立了连接,使用外部loop析构的时候大概率会崩。后面用Udp试了一下,也有这个问题。winodows上出现了,linux上跑了几遍没复现。库是直接用vs studio+源码的cmake编译的。
…------------------ 原始邮件 ------------------
发件人: ***@***.***>;
发送时间: 2025年4月2日(星期三) 凌晨5:11
收件人: ***@***.***>;
抄送: ***@***.***>; ***@***.***>;
主题: Re: [ithewei/libhv] 多个TcpClient/UdpClient共用一个EventLoop,析构时有概率崩溃 (Issue #704)
原因是执行启动的时候 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.png (view on web)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.Message ID: ***@***.***>
House-Men left a comment (ithewei/libhv#704)
原因是执行启动的时候 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.png (view on web)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
析构会崩问题同源,就像之前那个onClose析构后触发会崩溃的优化提交和你这个例子会析构后触发startRecv崩溃,本质上都是同一个原因,只要用到外部loop内部的停止逻辑都不会等待终止线程,所以你只要出现析构后loop触发了什么事件回调在回调处理中又用到被释放的对象成员数据就会崩溃。但并不是百分百触发,有时候会因为运行环境的不同对象释放后内存被填充成0导致某些异步回调触发判断是否为空条件成立从而避免崩溃。 |
是的,这种方式必须十分小心TcpClient/UdpClient的生命周期,最好的实践是使用堆对象,然后调用loop->runInLoop{delete cli;}在事件循环所在线程里删除对象,参考这个示例程序 |
The text was updated successfully, but these errors were encountered: