如何让libevent的线程优雅的退出

时间:2021-05-17 00:18:58
下面是一个专门用来处理libevent的线程的代码 (不好描述啊...但我想大家应该懂得我说的)

sometype * obj = nullptr;
resource * res = nullptr;
do
{
    obj = new sometype;
    if (nullptr == obj)
    {
        break;
    }

    res = new resource;
    if (nullptr == res)
    {
        break;
    }

    event_base_dispatch(base);
} while (false);

delete sometype;
delete resource;

我们知道程序会一直阻塞(不能叫阻塞,但暂且这么说吧)在event_base_dispatch(base);
windows调试时,在delete处断点,当程序退出时(我只知道关闭程序或者shift+F5来退出),但断点没跑过来
所以,我想程序是否有执行这一句? 

其实,就是想问一个问题,如果让此线程优雅的退出

我想,可能要创建一个event(具体是什么事件没想出来),退出时,调用这个event的回调(回调中处理资源的释放问题),但退出时会触发一个什么事件呢,不清楚啊...

47 个解决方案

#1



delete obj;
delete res;

....

#2


event_loopbreak

#3


引用 2 楼 spirit008 的回复:
event_loopbreak

谢谢,我先看看怎么用

#4


不要企图优雅的结束(因为这是不可能办到的)
而要在烂的不能再烂的摊子上也能重整河山!

#5


引用 4 楼 zhao4zhong1 的回复:
不要企图优雅的结束(因为这是不可能办到的)
而要在烂的不能再烂的摊子上也能重整河山!

我就知道你会这么说...  如何让libevent的线程优雅的退出

#6


引用 5 楼 ken_scott 的回复:
Quote: 引用 4 楼 zhao4zhong1 的回复:

不要企图优雅的结束(因为这是不可能办到的)
而要在烂的不能再烂的摊子上也能重整河山!

我就知道你会这么说...  如何让libevent的线程优雅的退出

那你知不知道当你想让libevent的线程优雅地退出时,可能会停电、地震、海啸或者世界末日呢? 如何让libevent的线程优雅的退出

#7


引用 6 楼 zhao4zhong1 的回复:
Quote: 引用 5 楼 ken_scott 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

不要企图优雅的结束(因为这是不可能办到的)
而要在烂的不能再烂的摊子上也能重整河山!

我就知道你会这么说...  如何让libevent的线程优雅的退出

那你知不知道当你想让libevent的线程优雅地退出时,可能会停电、地震、海啸或者世界末日呢? 如何让libevent的线程优雅的退出

额 造谣是会被抓的

#8


关于 event_loopbreak()
没看到具体应该怎么做,不过我想可能是在某个事件的回调函数中来调用它吧,但这个事件应该是个什么样的事件呢 (或者说,怎样能在程序退出时触发这个事件,然后调用event_loopbreak()来跳出loop,释放资源) ?

#9


引用 6 楼 zhao4zhong1 的回复:
Quote: 引用 5 楼 ken_scott 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

不要企图优雅的结束(因为这是不可能办到的)
而要在烂的不能再烂的摊子上也能重整河山!

我就知道你会这么说...  如何让libevent的线程优雅的退出

那你知不知道当你想让libevent的线程优雅地退出时,可能会停电、地震、海啸或者世界末日呢? 如何让libevent的线程优雅的退出

尽人力听天命,这种小概率事件发生了,我也没办法啊

#10


本来就是一个线程的东西,怎么样算是达到了优雅的效果呢?

#11


引用 10 楼 max_min_ 的回复:
本来就是一个线程的东西,怎么样算是达到了优雅的效果呢?

就像上面的代码,程序正常跑起来后,一定会内存泄漏的,因为后面的代码跑不到

#12


我想让这个线程释放所有的资源再结束,而上面的代码其实还有很多东西跑不到

#13


引用 11 楼 ken_scott 的回复:
Quote: 引用 10 楼 max_min_ 的回复:

本来就是一个线程的东西,怎么样算是达到了优雅的效果呢?

就像上面的代码,程序正常跑起来后,一定会内存泄漏的,因为后面的代码跑不到

内存泄漏和 线程优雅退出没有关系吧!
一个是代码严重bug,一个是优化代码!

#14


引用 13 楼 max_min_ 的回复:
Quote: 引用 11 楼 ken_scott 的回复:

Quote: 引用 10 楼 max_min_ 的回复:

本来就是一个线程的东西,怎么样算是达到了优雅的效果呢?

就像上面的代码,程序正常跑起来后,一定会内存泄漏的,因为后面的代码跑不到

内存泄漏和 线程优雅退出没有关系吧!
一个是代码严重bug,一个是优化代码!

你看APUE、UNP的例子,很多都不释放内存了,因为他们觉得反正程序退出会回收内存
其实,也算内存泄漏吧

#15


看上去代码所在的线程应该是自己负责的没有人去控制,如果有控制的,可以把资源释放注册到控制者上面,
然后控制者去中止线程,然后做资源检测。如果没有控制的,可以注册到某个全局的东西上,比如某个对象的析构函数,不过这样的风险大,存在依赖问题。还或者不用动态分配的资源,直接用静态的。至于断电,海啸的,尽人事,听天命吧。

#16


引用 14 楼 ken_scott 的回复:
Quote: 引用 13 楼 max_min_ 的回复:

Quote: 引用 11 楼 ken_scott 的回复:

Quote: 引用 10 楼 max_min_ 的回复:

本来就是一个线程的东西,怎么样算是达到了优雅的效果呢?

就像上面的代码,程序正常跑起来后,一定会内存泄漏的,因为后面的代码跑不到

内存泄漏和 线程优雅退出没有关系吧!
一个是代码严重bug,一个是优化代码!

你看APUE、UNP的例子,很多都不释放内存了,因为他们觉得反正程序退出会回收内存
其实,也算内存泄漏吧

其实那些例子,稍微改一下就可以释放内存了,也就是我所谓的优雅退出

#17


引用 15 楼 baihacker 的回复:
看上去代码所在的线程应该是自己负责的没有人去控制,如果有控制的,可以把资源释放注册到控制者上面,
然后控制者去中止线程,然后做资源检测。如果没有控制的,可以注册到某个全局的东西上,比如某个对象的析构函数,不过这样的风险大,存在依赖问题。还或者不用动态分配的资源,直接用静态的。至于断电,海啸的,尽人事,听天命吧。

这可能是baihacker第一次回复我的帖子,好激动,哈哈....

可以把资源释放注册到控制者上面,
然后控制者去中止线程,然后做资源检测。如果没有控制的,可以注册到某个全局的东西上,比如某个对象的析构函数

是一种解决思路,谢谢!!!
(如果没有更好的办法,就把整个对象在主线程创建,传入子线程,然后,子线程退出后,在主线程来释放资源)

#18


引用 14 楼 ken_scott 的回复:
Quote: 引用 13 楼 max_min_ 的回复:

Quote: 引用 11 楼 ken_scott 的回复:

Quote: 引用 10 楼 max_min_ 的回复:

本来就是一个线程的东西,怎么样算是达到了优雅的效果呢?

就像上面的代码,程序正常跑起来后,一定会内存泄漏的,因为后面的代码跑不到

内存泄漏和 线程优雅退出没有关系吧!
一个是代码严重bug,一个是优化代码!

你看APUE、UNP的例子,很多都不释放内存了,因为他们觉得反正程序退出会回收内存
其实,也算内存泄漏吧


对于内存的释放问题,一般都是遵循谁分配 谁释放的原则!因为毕竟只有自己才知道什么时候用完已经不再需要用的!当然你也可以告诉其他线程,什么时候不需要用了,叫它们帮忙也是可以的!这个时候就注意该什么时候告诉这个动作了!

#19


个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

#20


监听pipe管道, write 1字节唤醒退出, join回收线程。

#21


引用 18 楼 max_min_ 的回复:
Quote: 引用 14 楼 ken_scott 的回复:

Quote: 引用 13 楼 max_min_ 的回复:

Quote: 引用 11 楼 ken_scott 的回复:

Quote: 引用 10 楼 max_min_ 的回复:

本来就是一个线程的东西,怎么样算是达到了优雅的效果呢?

就像上面的代码,程序正常跑起来后,一定会内存泄漏的,因为后面的代码跑不到

内存泄漏和 线程优雅退出没有关系吧!
一个是代码严重bug,一个是优化代码!

你看APUE、UNP的例子,很多都不释放内存了,因为他们觉得反正程序退出会回收内存
其实,也算内存泄漏吧


对于内存的释放问题,一般都是遵循谁分配 谁释放的原则!因为毕竟只有自己才知道什么时候用完已经不再需要用的!当然你也可以告诉其他线程,什么时候不需要用了,叫它们帮忙也是可以的!这个时候就注意该什么时候告诉这个动作了!

资源释放的问题,理论上是这样来

#22


引用 19 楼 zhao4zhong1 的回复:
个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

exit(1);连析构函数都来不及调用 (比如,ATM机,你不工作可以,得把卡先退出来吧)

#23


引用 20 楼 qq120848369 的回复:
监听pipe管道, write 1字节唤醒退出, join回收线程。

谢谢,这让我想到,可以主线程或许可以通过类似是方式写一个事件,事件触发是调用event_loopbreak()试试

#24


引用 22 楼 ken_scott 的回复:
Quote: 引用 19 楼 zhao4zhong1 的回复:

个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

exit(1);连析构函数都来不及调用 (比如,ATM机,你不工作可以,得把卡先退出来吧)

退卡的动作不是在析构函数里面启动的,而是在系统重启或加电后“重整河山”时发现上次死机或掉电时的“烂摊子”里面有一张卡需要退出时启动的。

#25


引用 24 楼 zhao4zhong1 的回复:
Quote: 引用 22 楼 ken_scott 的回复:

Quote: 引用 19 楼 zhao4zhong1 的回复:

个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

exit(1);连析构函数都来不及调用 (比如,ATM机,你不工作可以,得把卡先退出来吧)

退卡的动作不是在析构函数里面启动的,而是在系统重启或加电后“重整河山”时发现上次死机或掉电时的“烂摊子”里面有一张卡需要退出时启动的。

析构的时候检查是否有卡,有则退卡,不是更好么?

#26


引用 25 楼 ken_scott 的回复:
Quote: 引用 24 楼 zhao4zhong1 的回复:

Quote: 引用 22 楼 ken_scott 的回复:

Quote: 引用 19 楼 zhao4zhong1 的回复:

个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

exit(1);连析构函数都来不及调用 (比如,ATM机,你不工作可以,得把卡先退出来吧)

退卡的动作不是在析构函数里面启动的,而是在系统重启或加电后“重整河山”时发现上次死机或掉电时的“烂摊子”里面有一张卡需要退出时启动的。

析构的时候检查是否有卡,有则退卡,不是更好么?

不好。因为万一析构的时候掉电呢?
就算不考虑掉电这种比较极端的情况,那也应该在构造的时候判断如果有卡需要退出时退卡。

#27


整个对象已经改成单件,程序的退出正常了,但流程特别有意思:

当程序退出时,调用单件的析构函数,析构函数中开始释放资源,当释放了所有绑定在base上的事件后,子线程从event_base_dispatch处返回,子线程正常结束,同时单件也释放了base(改成一个子对象)及其他资源。

#28


引用 26 楼 zhao4zhong1 的回复:
Quote: 引用 25 楼 ken_scott 的回复:

Quote: 引用 24 楼 zhao4zhong1 的回复:

Quote: 引用 22 楼 ken_scott 的回复:

Quote: 引用 19 楼 zhao4zhong1 的回复:

个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

exit(1);连析构函数都来不及调用 (比如,ATM机,你不工作可以,得把卡先退出来吧)

退卡的动作不是在析构函数里面启动的,而是在系统重启或加电后“重整河山”时发现上次死机或掉电时的“烂摊子”里面有一张卡需要退出时启动的。

析构的时候检查是否有卡,有则退卡,不是更好么?

不好。因为万一析构的时候掉电呢?
就算不考虑掉电这种比较极端的情况,那也应该在构造的时候判断如果有卡需要退出时退卡。

析构函数可以这么写啊

bool has_card = read_database(); // maybe like this
if (has_card)
{
    release_card();
    write_database(false);
}

#29


引用 28 楼 ken_scott 的回复:
Quote: 引用 26 楼 zhao4zhong1 的回复:

Quote: 引用 25 楼 ken_scott 的回复:

Quote: 引用 24 楼 zhao4zhong1 的回复:

Quote: 引用 22 楼 ken_scott 的回复:

Quote: 引用 19 楼 zhao4zhong1 的回复:

个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

exit(1);连析构函数都来不及调用 (比如,ATM机,你不工作可以,得把卡先退出来吧)

退卡的动作不是在析构函数里面启动的,而是在系统重启或加电后“重整河山”时发现上次死机或掉电时的“烂摊子”里面有一张卡需要退出时启动的。

析构的时候检查是否有卡,有则退卡,不是更好么?

不好。因为万一析构的时候掉电呢?
就算不考虑掉电这种比较极端的情况,那也应该在构造的时候判断如果有卡需要退出时退卡。

析构函数可以这么写啊

bool has_card = read_database(); // maybe like this
if (has_card)
{
    release_card();
    write_database(false);
}

或者不管有没有卡,都先尝试退一次,没退成功就算了

#30


想7×24小时稳定运行的程序
最好在运行过程中避免动态创建/销毁或申请/释放各种对象;
而应在初始化时先清理上次正常或异常退出导致的各种内部外部资源的占用,创建或申请足够使用的各种对象并将它们池化,然后进入主循环开始工作,工作中只改变池中各资源的使用/待用状态。
如何让libevent的线程优雅的退出

#31


检查是否资源泄漏的办法之一:
在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象
让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!

#32


引用 29 楼 ken_scott 的回复:
Quote: 引用 28 楼 ken_scott 的回复:

Quote: 引用 26 楼 zhao4zhong1 的回复:

Quote: 引用 25 楼 ken_scott 的回复:

Quote: 引用 24 楼 zhao4zhong1 的回复:

Quote: 引用 22 楼 ken_scott 的回复:

Quote: 引用 19 楼 zhao4zhong1 的回复:

个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

exit(1);连析构函数都来不及调用 (比如,ATM机,你不工作可以,得把卡先退出来吧)

退卡的动作不是在析构函数里面启动的,而是在系统重启或加电后“重整河山”时发现上次死机或掉电时的“烂摊子”里面有一张卡需要退出时启动的。

析构的时候检查是否有卡,有则退卡,不是更好么?

不好。因为万一析构的时候掉电呢?
就算不考虑掉电这种比较极端的情况,那也应该在构造的时候判断如果有卡需要退出时退卡。

析构函数可以这么写啊

bool has_card = read_database(); // maybe like this
if (has_card)
{
    release_card();
    write_database(false);
}

或者不管有没有卡,都先尝试退一次,没退成功就算了

既然在构造时必须判断是否有卡要退有则退,就没必要在析构时判断是否有卡要退有则退了。(←象不象绕口令) 如何让libevent的线程优雅的退出

#33


你的线程这样写,表示在别的地方没有需要让她结束的要求。否则就会有 cancel 标识。
那么旧部需要考虑结束。
如果,整个进程被终结了,该线程无论怎么结束都是优雅的。

#34


通俗点说就是
假如两个人先后在ATM机上操作,分割两人操作的关键点:
并不是在第一个人析构之后第二个人构造之前;
而是在第二个人构造开始时清理前一个人留下的现场以确保各种条件符合了,准备为第二个人开始服务之后。

#35


引用 32 楼 zhao4zhong1 的回复:
既然在构造时必须判断是否有卡要退有则退,就没必要在析构时判断是否有卡要退有则退了。(←象不象绕口令) 如何让libevent的线程优雅的退出

28L时,我考虑比较严格,所以做了检查判定
29L时,我想,懒一点的话,这个判定是不必要的

总之,会应该尝试退卡,防止(尽量)退卡的问题

#36


引用 33 楼 Saleayas 的回复:
你的线程这样写,表示在别的地方没有需要让她结束的要求。否则就会有 cancel 标识。
那么旧部需要考虑结束。
如果,整个进程被终结了,该线程无论怎么结束都是优雅的。

最终确实会有cancel标识,比如MFC界面退出,我可能要释放资源

但就算系统会自动回收内存这样的资源,对有些资源、“任务”还是不行的,
比如,我可能要打印一条日志“proxy exit..., handle 123456 records”,这个系统没法帮我做的,我必须保证程序退出后有正确地做这件事(比如放在析构函数做),但必须保证析构函数被调用到 (进程终结并不能保证这一点)

#37


帖主关键还是不承认我这句话
不要企图优雅的结束(因为这是不可能办到的)
而要在烂的不能再烂的摊子上也能重整河山!
中蕴含的哲学(但事实确实如此!)。

#38


引用 34 楼 zhao4zhong1 的回复:
通俗点说就是
假如两个人先后在ATM机上操作,分割两人操作的关键点:
并不是在第一个人析构之后第二个人构造之前;
而是在第二个人构造开始时清理前一个人留下的现场以确保各种条件符合了,准备为第二个人开始服务之后。

这样还不够人性化吧

可以尝试在前一个任务结束的时候处理异常(比如,退卡)
在处理下一个任务之前也处理异常(万一,上次真的停电了啥的)

这样虽然多尝试了一次,但已经是尽最大努力完成异常处理了,如果客户还不满意,也不用后悔,因为已经尽力去做了这件事 (如果能程序结束的时候退卡,为什么要等到程序重启呢?如果不成功,那还可以理解,但是尽力了,无悔了)

#39


虎头蛇尾是俗人的习惯,
有始有终是君子的操守。

#40


建议帖主了解一下数据库系统是怎样实现事务的。

#41


引用 40 楼 zhao4zhong1 的回复:
建议帖主了解一下数据库系统是怎样实现事务的。

确实不了解,上面的例子是乱写的

#42


如果是这样,就像 赵老师说的,优雅的结束很难。

不过可以象 Windows 蓝屏保护那样。
不管是否洪水滔天,我依然蓝屏保护。

#43


引用 42 楼 Saleayas 的回复:
如果是这样,就像 赵老师说的,优雅的结束很难。

不过可以象 Windows 蓝屏保护那样。
不管是否洪水滔天,我依然蓝屏保护。

程序异常挂了,这个可能也没办法(...)
但是正常情形下,还是希望尽量能优雅地退出

#44


引用 40 楼 zhao4zhong1 的回复:
建议帖主了解一下数据库系统是怎样实现事务的。

建议回答问题要到正题上去,别搞太虚的道理。

#45


引用 44 楼 yulongying 的回复:
Quote: 引用 40 楼 zhao4zhong1 的回复:

建议帖主了解一下数据库系统是怎样实现事务的。

建议回答问题要到正题上去,别搞太虚的道理。

挖坟可耻!

#46


引用 30 楼 zhao4zhong1 的回复:
想7×24小时稳定运行的程序
最好在运行过程中避免动态创建/销毁或申请/释放各种对象;
而应在初始化时先清理上次正常或异常退出导致的各种内部外部资源的占用,创建或申请足够使用的各种对象并将它们池化,然后进入主循环开始工作,工作中只改变池中各资源的使用/待用状态。
如何让libevent的线程优雅的退出


需要先实现内存池机制,而且建议只用于可以常驻或需要常驻的对象。
试想,如果所需的全部内存超大,又该如何?

#47


仅就LZ的原问题而言,只有二楼是对的。

event_dispatch/event_base_dispatch的终止,需要你的程序主动触发,而不是响应什么事件了。
可调用:event_loopbreak/event_base_loopbreak或者event_loopexit/event_base_loopexit,建议使用后者。
实际上就是分别设置了libevent内置的两个标记量,这两个标记量都会使得dispatch方法中内置的循环退出,
之后就会执行调用dispatch方法的语句后面的内容了。

参考这篇文章:
http://blog.csdn.net/yusiguyuan/article/details/18262151

#1



delete obj;
delete res;

....

#2


event_loopbreak

#3


引用 2 楼 spirit008 的回复:
event_loopbreak

谢谢,我先看看怎么用

#4


不要企图优雅的结束(因为这是不可能办到的)
而要在烂的不能再烂的摊子上也能重整河山!

#5


引用 4 楼 zhao4zhong1 的回复:
不要企图优雅的结束(因为这是不可能办到的)
而要在烂的不能再烂的摊子上也能重整河山!

我就知道你会这么说...  如何让libevent的线程优雅的退出

#6


引用 5 楼 ken_scott 的回复:
Quote: 引用 4 楼 zhao4zhong1 的回复:

不要企图优雅的结束(因为这是不可能办到的)
而要在烂的不能再烂的摊子上也能重整河山!

我就知道你会这么说...  如何让libevent的线程优雅的退出

那你知不知道当你想让libevent的线程优雅地退出时,可能会停电、地震、海啸或者世界末日呢? 如何让libevent的线程优雅的退出

#7


引用 6 楼 zhao4zhong1 的回复:
Quote: 引用 5 楼 ken_scott 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

不要企图优雅的结束(因为这是不可能办到的)
而要在烂的不能再烂的摊子上也能重整河山!

我就知道你会这么说...  如何让libevent的线程优雅的退出

那你知不知道当你想让libevent的线程优雅地退出时,可能会停电、地震、海啸或者世界末日呢? 如何让libevent的线程优雅的退出

额 造谣是会被抓的

#8


关于 event_loopbreak()
没看到具体应该怎么做,不过我想可能是在某个事件的回调函数中来调用它吧,但这个事件应该是个什么样的事件呢 (或者说,怎样能在程序退出时触发这个事件,然后调用event_loopbreak()来跳出loop,释放资源) ?

#9


引用 6 楼 zhao4zhong1 的回复:
Quote: 引用 5 楼 ken_scott 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

不要企图优雅的结束(因为这是不可能办到的)
而要在烂的不能再烂的摊子上也能重整河山!

我就知道你会这么说...  如何让libevent的线程优雅的退出

那你知不知道当你想让libevent的线程优雅地退出时,可能会停电、地震、海啸或者世界末日呢? 如何让libevent的线程优雅的退出

尽人力听天命,这种小概率事件发生了,我也没办法啊

#10


本来就是一个线程的东西,怎么样算是达到了优雅的效果呢?

#11


引用 10 楼 max_min_ 的回复:
本来就是一个线程的东西,怎么样算是达到了优雅的效果呢?

就像上面的代码,程序正常跑起来后,一定会内存泄漏的,因为后面的代码跑不到

#12


我想让这个线程释放所有的资源再结束,而上面的代码其实还有很多东西跑不到

#13


引用 11 楼 ken_scott 的回复:
Quote: 引用 10 楼 max_min_ 的回复:

本来就是一个线程的东西,怎么样算是达到了优雅的效果呢?

就像上面的代码,程序正常跑起来后,一定会内存泄漏的,因为后面的代码跑不到

内存泄漏和 线程优雅退出没有关系吧!
一个是代码严重bug,一个是优化代码!

#14


引用 13 楼 max_min_ 的回复:
Quote: 引用 11 楼 ken_scott 的回复:

Quote: 引用 10 楼 max_min_ 的回复:

本来就是一个线程的东西,怎么样算是达到了优雅的效果呢?

就像上面的代码,程序正常跑起来后,一定会内存泄漏的,因为后面的代码跑不到

内存泄漏和 线程优雅退出没有关系吧!
一个是代码严重bug,一个是优化代码!

你看APUE、UNP的例子,很多都不释放内存了,因为他们觉得反正程序退出会回收内存
其实,也算内存泄漏吧

#15


看上去代码所在的线程应该是自己负责的没有人去控制,如果有控制的,可以把资源释放注册到控制者上面,
然后控制者去中止线程,然后做资源检测。如果没有控制的,可以注册到某个全局的东西上,比如某个对象的析构函数,不过这样的风险大,存在依赖问题。还或者不用动态分配的资源,直接用静态的。至于断电,海啸的,尽人事,听天命吧。

#16


引用 14 楼 ken_scott 的回复:
Quote: 引用 13 楼 max_min_ 的回复:

Quote: 引用 11 楼 ken_scott 的回复:

Quote: 引用 10 楼 max_min_ 的回复:

本来就是一个线程的东西,怎么样算是达到了优雅的效果呢?

就像上面的代码,程序正常跑起来后,一定会内存泄漏的,因为后面的代码跑不到

内存泄漏和 线程优雅退出没有关系吧!
一个是代码严重bug,一个是优化代码!

你看APUE、UNP的例子,很多都不释放内存了,因为他们觉得反正程序退出会回收内存
其实,也算内存泄漏吧

其实那些例子,稍微改一下就可以释放内存了,也就是我所谓的优雅退出

#17


引用 15 楼 baihacker 的回复:
看上去代码所在的线程应该是自己负责的没有人去控制,如果有控制的,可以把资源释放注册到控制者上面,
然后控制者去中止线程,然后做资源检测。如果没有控制的,可以注册到某个全局的东西上,比如某个对象的析构函数,不过这样的风险大,存在依赖问题。还或者不用动态分配的资源,直接用静态的。至于断电,海啸的,尽人事,听天命吧。

这可能是baihacker第一次回复我的帖子,好激动,哈哈....

可以把资源释放注册到控制者上面,
然后控制者去中止线程,然后做资源检测。如果没有控制的,可以注册到某个全局的东西上,比如某个对象的析构函数

是一种解决思路,谢谢!!!
(如果没有更好的办法,就把整个对象在主线程创建,传入子线程,然后,子线程退出后,在主线程来释放资源)

#18


引用 14 楼 ken_scott 的回复:
Quote: 引用 13 楼 max_min_ 的回复:

Quote: 引用 11 楼 ken_scott 的回复:

Quote: 引用 10 楼 max_min_ 的回复:

本来就是一个线程的东西,怎么样算是达到了优雅的效果呢?

就像上面的代码,程序正常跑起来后,一定会内存泄漏的,因为后面的代码跑不到

内存泄漏和 线程优雅退出没有关系吧!
一个是代码严重bug,一个是优化代码!

你看APUE、UNP的例子,很多都不释放内存了,因为他们觉得反正程序退出会回收内存
其实,也算内存泄漏吧


对于内存的释放问题,一般都是遵循谁分配 谁释放的原则!因为毕竟只有自己才知道什么时候用完已经不再需要用的!当然你也可以告诉其他线程,什么时候不需要用了,叫它们帮忙也是可以的!这个时候就注意该什么时候告诉这个动作了!

#19


个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

#20


监听pipe管道, write 1字节唤醒退出, join回收线程。

#21


引用 18 楼 max_min_ 的回复:
Quote: 引用 14 楼 ken_scott 的回复:

Quote: 引用 13 楼 max_min_ 的回复:

Quote: 引用 11 楼 ken_scott 的回复:

Quote: 引用 10 楼 max_min_ 的回复:

本来就是一个线程的东西,怎么样算是达到了优雅的效果呢?

就像上面的代码,程序正常跑起来后,一定会内存泄漏的,因为后面的代码跑不到

内存泄漏和 线程优雅退出没有关系吧!
一个是代码严重bug,一个是优化代码!

你看APUE、UNP的例子,很多都不释放内存了,因为他们觉得反正程序退出会回收内存
其实,也算内存泄漏吧


对于内存的释放问题,一般都是遵循谁分配 谁释放的原则!因为毕竟只有自己才知道什么时候用完已经不再需要用的!当然你也可以告诉其他线程,什么时候不需要用了,叫它们帮忙也是可以的!这个时候就注意该什么时候告诉这个动作了!

资源释放的问题,理论上是这样来

#22


引用 19 楼 zhao4zhong1 的回复:
个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

exit(1);连析构函数都来不及调用 (比如,ATM机,你不工作可以,得把卡先退出来吧)

#23


引用 20 楼 qq120848369 的回复:
监听pipe管道, write 1字节唤醒退出, join回收线程。

谢谢,这让我想到,可以主线程或许可以通过类似是方式写一个事件,事件触发是调用event_loopbreak()试试

#24


引用 22 楼 ken_scott 的回复:
Quote: 引用 19 楼 zhao4zhong1 的回复:

个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

exit(1);连析构函数都来不及调用 (比如,ATM机,你不工作可以,得把卡先退出来吧)

退卡的动作不是在析构函数里面启动的,而是在系统重启或加电后“重整河山”时发现上次死机或掉电时的“烂摊子”里面有一张卡需要退出时启动的。

#25


引用 24 楼 zhao4zhong1 的回复:
Quote: 引用 22 楼 ken_scott 的回复:

Quote: 引用 19 楼 zhao4zhong1 的回复:

个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

exit(1);连析构函数都来不及调用 (比如,ATM机,你不工作可以,得把卡先退出来吧)

退卡的动作不是在析构函数里面启动的,而是在系统重启或加电后“重整河山”时发现上次死机或掉电时的“烂摊子”里面有一张卡需要退出时启动的。

析构的时候检查是否有卡,有则退卡,不是更好么?

#26


引用 25 楼 ken_scott 的回复:
Quote: 引用 24 楼 zhao4zhong1 的回复:

Quote: 引用 22 楼 ken_scott 的回复:

Quote: 引用 19 楼 zhao4zhong1 的回复:

个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

exit(1);连析构函数都来不及调用 (比如,ATM机,你不工作可以,得把卡先退出来吧)

退卡的动作不是在析构函数里面启动的,而是在系统重启或加电后“重整河山”时发现上次死机或掉电时的“烂摊子”里面有一张卡需要退出时启动的。

析构的时候检查是否有卡,有则退卡,不是更好么?

不好。因为万一析构的时候掉电呢?
就算不考虑掉电这种比较极端的情况,那也应该在构造的时候判断如果有卡需要退出时退卡。

#27


整个对象已经改成单件,程序的退出正常了,但流程特别有意思:

当程序退出时,调用单件的析构函数,析构函数中开始释放资源,当释放了所有绑定在base上的事件后,子线程从event_base_dispatch处返回,子线程正常结束,同时单件也释放了base(改成一个子对象)及其他资源。

#28


引用 26 楼 zhao4zhong1 的回复:
Quote: 引用 25 楼 ken_scott 的回复:

Quote: 引用 24 楼 zhao4zhong1 的回复:

Quote: 引用 22 楼 ken_scott 的回复:

Quote: 引用 19 楼 zhao4zhong1 的回复:

个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

exit(1);连析构函数都来不及调用 (比如,ATM机,你不工作可以,得把卡先退出来吧)

退卡的动作不是在析构函数里面启动的,而是在系统重启或加电后“重整河山”时发现上次死机或掉电时的“烂摊子”里面有一张卡需要退出时启动的。

析构的时候检查是否有卡,有则退卡,不是更好么?

不好。因为万一析构的时候掉电呢?
就算不考虑掉电这种比较极端的情况,那也应该在构造的时候判断如果有卡需要退出时退卡。

析构函数可以这么写啊

bool has_card = read_database(); // maybe like this
if (has_card)
{
    release_card();
    write_database(false);
}

#29


引用 28 楼 ken_scott 的回复:
Quote: 引用 26 楼 zhao4zhong1 的回复:

Quote: 引用 25 楼 ken_scott 的回复:

Quote: 引用 24 楼 zhao4zhong1 的回复:

Quote: 引用 22 楼 ken_scott 的回复:

Quote: 引用 19 楼 zhao4zhong1 的回复:

个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

exit(1);连析构函数都来不及调用 (比如,ATM机,你不工作可以,得把卡先退出来吧)

退卡的动作不是在析构函数里面启动的,而是在系统重启或加电后“重整河山”时发现上次死机或掉电时的“烂摊子”里面有一张卡需要退出时启动的。

析构的时候检查是否有卡,有则退卡,不是更好么?

不好。因为万一析构的时候掉电呢?
就算不考虑掉电这种比较极端的情况,那也应该在构造的时候判断如果有卡需要退出时退卡。

析构函数可以这么写啊

bool has_card = read_database(); // maybe like this
if (has_card)
{
    release_card();
    write_database(false);
}

或者不管有没有卡,都先尝试退一次,没退成功就算了

#30


想7×24小时稳定运行的程序
最好在运行过程中避免动态创建/销毁或申请/释放各种对象;
而应在初始化时先清理上次正常或异常退出导致的各种内部外部资源的占用,创建或申请足够使用的各种对象并将它们池化,然后进入主循环开始工作,工作中只改变池中各资源的使用/待用状态。
如何让libevent的线程优雅的退出

#31


检查是否资源泄漏的办法之一:
在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象
让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!

#32


引用 29 楼 ken_scott 的回复:
Quote: 引用 28 楼 ken_scott 的回复:

Quote: 引用 26 楼 zhao4zhong1 的回复:

Quote: 引用 25 楼 ken_scott 的回复:

Quote: 引用 24 楼 zhao4zhong1 的回复:

Quote: 引用 22 楼 ken_scott 的回复:

Quote: 引用 19 楼 zhao4zhong1 的回复:

个人意见,最优雅的退出方式是exit(1);
参考《Unix编程艺术》

exit(1);连析构函数都来不及调用 (比如,ATM机,你不工作可以,得把卡先退出来吧)

退卡的动作不是在析构函数里面启动的,而是在系统重启或加电后“重整河山”时发现上次死机或掉电时的“烂摊子”里面有一张卡需要退出时启动的。

析构的时候检查是否有卡,有则退卡,不是更好么?

不好。因为万一析构的时候掉电呢?
就算不考虑掉电这种比较极端的情况,那也应该在构造的时候判断如果有卡需要退出时退卡。

析构函数可以这么写啊

bool has_card = read_database(); // maybe like this
if (has_card)
{
    release_card();
    write_database(false);
}

或者不管有没有卡,都先尝试退一次,没退成功就算了

既然在构造时必须判断是否有卡要退有则退,就没必要在析构时判断是否有卡要退有则退了。(←象不象绕口令) 如何让libevent的线程优雅的退出

#33


你的线程这样写,表示在别的地方没有需要让她结束的要求。否则就会有 cancel 标识。
那么旧部需要考虑结束。
如果,整个进程被终结了,该线程无论怎么结束都是优雅的。

#34


通俗点说就是
假如两个人先后在ATM机上操作,分割两人操作的关键点:
并不是在第一个人析构之后第二个人构造之前;
而是在第二个人构造开始时清理前一个人留下的现场以确保各种条件符合了,准备为第二个人开始服务之后。

#35


引用 32 楼 zhao4zhong1 的回复:
既然在构造时必须判断是否有卡要退有则退,就没必要在析构时判断是否有卡要退有则退了。(←象不象绕口令) 如何让libevent的线程优雅的退出

28L时,我考虑比较严格,所以做了检查判定
29L时,我想,懒一点的话,这个判定是不必要的

总之,会应该尝试退卡,防止(尽量)退卡的问题

#36


引用 33 楼 Saleayas 的回复:
你的线程这样写,表示在别的地方没有需要让她结束的要求。否则就会有 cancel 标识。
那么旧部需要考虑结束。
如果,整个进程被终结了,该线程无论怎么结束都是优雅的。

最终确实会有cancel标识,比如MFC界面退出,我可能要释放资源

但就算系统会自动回收内存这样的资源,对有些资源、“任务”还是不行的,
比如,我可能要打印一条日志“proxy exit..., handle 123456 records”,这个系统没法帮我做的,我必须保证程序退出后有正确地做这件事(比如放在析构函数做),但必须保证析构函数被调用到 (进程终结并不能保证这一点)

#37


帖主关键还是不承认我这句话
不要企图优雅的结束(因为这是不可能办到的)
而要在烂的不能再烂的摊子上也能重整河山!
中蕴含的哲学(但事实确实如此!)。

#38


引用 34 楼 zhao4zhong1 的回复:
通俗点说就是
假如两个人先后在ATM机上操作,分割两人操作的关键点:
并不是在第一个人析构之后第二个人构造之前;
而是在第二个人构造开始时清理前一个人留下的现场以确保各种条件符合了,准备为第二个人开始服务之后。

这样还不够人性化吧

可以尝试在前一个任务结束的时候处理异常(比如,退卡)
在处理下一个任务之前也处理异常(万一,上次真的停电了啥的)

这样虽然多尝试了一次,但已经是尽最大努力完成异常处理了,如果客户还不满意,也不用后悔,因为已经尽力去做了这件事 (如果能程序结束的时候退卡,为什么要等到程序重启呢?如果不成功,那还可以理解,但是尽力了,无悔了)

#39


虎头蛇尾是俗人的习惯,
有始有终是君子的操守。

#40


建议帖主了解一下数据库系统是怎样实现事务的。

#41


引用 40 楼 zhao4zhong1 的回复:
建议帖主了解一下数据库系统是怎样实现事务的。

确实不了解,上面的例子是乱写的

#42


如果是这样,就像 赵老师说的,优雅的结束很难。

不过可以象 Windows 蓝屏保护那样。
不管是否洪水滔天,我依然蓝屏保护。

#43


引用 42 楼 Saleayas 的回复:
如果是这样,就像 赵老师说的,优雅的结束很难。

不过可以象 Windows 蓝屏保护那样。
不管是否洪水滔天,我依然蓝屏保护。

程序异常挂了,这个可能也没办法(...)
但是正常情形下,还是希望尽量能优雅地退出

#44


引用 40 楼 zhao4zhong1 的回复:
建议帖主了解一下数据库系统是怎样实现事务的。

建议回答问题要到正题上去,别搞太虚的道理。

#45


引用 44 楼 yulongying 的回复:
Quote: 引用 40 楼 zhao4zhong1 的回复:

建议帖主了解一下数据库系统是怎样实现事务的。

建议回答问题要到正题上去,别搞太虚的道理。

挖坟可耻!

#46


引用 30 楼 zhao4zhong1 的回复:
想7×24小时稳定运行的程序
最好在运行过程中避免动态创建/销毁或申请/释放各种对象;
而应在初始化时先清理上次正常或异常退出导致的各种内部外部资源的占用,创建或申请足够使用的各种对象并将它们池化,然后进入主循环开始工作,工作中只改变池中各资源的使用/待用状态。
如何让libevent的线程优雅的退出


需要先实现内存池机制,而且建议只用于可以常驻或需要常驻的对象。
试想,如果所需的全部内存超大,又该如何?

#47


仅就LZ的原问题而言,只有二楼是对的。

event_dispatch/event_base_dispatch的终止,需要你的程序主动触发,而不是响应什么事件了。
可调用:event_loopbreak/event_base_loopbreak或者event_loopexit/event_base_loopexit,建议使用后者。
实际上就是分别设置了libevent内置的两个标记量,这两个标记量都会使得dispatch方法中内置的循环退出,
之后就会执行调用dispatch方法的语句后面的内容了。

参考这篇文章:
http://blog.csdn.net/yusiguyuan/article/details/18262151