增加 releasePool 使得外部可以主动释放Pollers #284
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
问题背景:
ZLMediaKit/ZLMediaKit#4580
更新代码到commit:8c9439571032a0db7d678a0104443125dc0d6916,在windows平台,编译Release版本的ZLMediaKit,并且勾选编译产物是动态库,然后启动MediaServer,之后按Ctrl+c 退出的时候,程序将无法正常退出,查看堆栈如下:
ntdll.dll!00007ff827e94a34() 未知
ZLToolKit.dll!reflock__await_event(void * address) 行 1382 C
ZLToolKit.dll!reflock_unref_and_destroy(reflock * reflock) 行 1415 C
ZLToolKit.dll!ts_tree_node_unref_and_destroy(ts_tree_node * node) 行 1786 C
ZLToolKit.dll!epoll_close(void * ephnd) 行 513 C
ZLToolKit.dll!toolkit::EventPoller::~EventPoller() 行 113 C++
ZLToolKit.dll!toolkit::EventPoller::scalar deleting destructor'(unsigned int) C++ ZLToolKit.dll!std::_Ref_counttoolkit::EventPoller::_Destroy() 行 1205 C++ ZLToolKit.dll!std::_Ref_count_base::_Decref() 行 1179 C++ ZLToolKit.dll!std::_Ptr_basetoolkit::TaskExecutor::_Decref() 行 1405 C++ ZLToolKit.dll!std::shared_ptrtoolkit::TaskExecutor::~shared_ptrtoolkit::TaskExecutor() 行 1688 C++ ZLToolKit.dll!std::shared_ptrtoolkit::TaskExecutor::scalar deleting destructor'(unsigned int) C++
ZLToolKit.dll!std::_Default_allocator_traits<std::allocatorstd::shared_ptrtoolkit::TaskExecutor>::destroystd::shared_ptrtoolkit::TaskExecutor(std::allocatorstd::shared_ptrtoolkit::TaskExecutor & __formal, std::shared_ptrtoolkit::TaskExecutor * const _Ptr) 行 730 C++
ZLToolKit.dll!std::_Destroy_range<std::allocatorstd::shared_ptrtoolkit::TaskExecutor>(std::shared_ptrtoolkit::TaskExecutor * _First, std::shared_ptrtoolkit::TaskExecutor * const Last, std::allocatorstd::shared_ptrtoolkit::TaskExecutor & Al) 行 1088 C++
ZLToolKit.dll!std::vector<std::shared_ptrtoolkit::TaskExecutor,std::allocatorstd::shared_ptrtoolkit::TaskExecutor>::Tidy() 行 2047 C++
ZLToolKit.dll!std::vector<std::shared_ptrtoolkit::TaskExecutor,std::allocatorstd::shared_ptrtoolkit::TaskExecutor>::~vector<std::shared_ptrtoolkit::TaskExecutor,std::allocatorstd::shared_ptrtoolkit::TaskExecutor>() 行 769 C++
ZLToolKit.dll!toolkit::TaskExecutorGetterImp::~TaskExecutorGetterImp() 行 262 C++
ZLToolKit.dll!toolkit::EventPollerPool::~EventPollerPool() 行 350 C++
ZLToolKit.dll!toolkit::EventPollerPool::scalar deleting destructor'(unsigned int) C++ ZLToolKit.dll!std::_Ref_counttoolkit::EventPollerPool::_Destroy() 行 1205 C++ ZLToolKit.dll!std::_Ref_count_base::_Decref() 行 1179 C++ ZLToolKit.dll!std::_Ptr_basetoolkit::EventPollerPool::_Decref() 行 1405 C++ ZLToolKit.dll!std::shared_ptrtoolkit::EventPollerPool::~shared_ptrtoolkit::EventPollerPool() 行 1688 C++ ZLToolKit.dll!toolkit::EventPollerPool::Instance'::2'::dynamic atexit destructor for 's_instance''() C++
ucrtbased.dll!00007fffa1442c21() 未知
ucrtbased.dll!00007fffa14423f5() 未知
ucrtbased.dll!00007fffa1442547() 未知
ucrtbased.dll!00007fffa1442e34() 未知
ZLToolKit.dll!scrt_dllmain_uninitialize_c() 行 399 C++
ZLToolKit.dll!dllmain_crt_process_detach(const bool is_terminating) 行 182 C++
ZLToolKit.dll!dllmain_crt_dispatch(HINSTANCE * const instance, const unsigned long reason, void * const reserved) 行 220 C++
ZLToolKit.dll!dllmain_dispatch(HINSTANCE * const instance, const unsigned long reason, void * const reserved) 行 293 C++
ZLToolKit.dll!DllMainCRTStartup(HINSTANCE * const instance, const unsigned long reason, void * const reserved) 行 335 C++
ntdll.dll!00007ff827e18bcf() 未知
ntdll.dll!00007ff827e415d6() 未知
ntdll.dll!00007ff827e411cd() 未知
kernel32.dll!00007ff825b77fcb() 未知
ucrtbased.dll!00007fffa1441eda() 未知
ucrtbased.dll!00007fffa1441e85() 未知
ucrtbased.dll!00007fffa14421f6() 未知
MediaServer.exe!__scrt_common_main_seh() 行 297 C++
MediaServer.exe!__scrt_common_main() 行 331 C++
MediaServer.exe!mainCRTStartup(void * __formal) 行 17 C++
kernel32.dll!00007ff825b7259d() 未知
ntdll.dll!00007ff827e4af78() 未知
原因分析:
在ZLMediakit的退出流程中,当程序退出的时候,会回收资源,包括EventPoller的回收,目前的EventPoller的析构会向pipe发送信号,然后触发poller线程激活,设置_exit_flag,并且跳出eventloop。如果这里的wirte失败的话(实际测试结果,这里可能出现报错,在windows上,错误号是10093),就可能导致eventloop线程处于阻塞状态,无法退出系统。
引起上述失败的原因就在于在系统退出的析构过程中,socket的调用是不安全的,所以我们在ZLTookKit这里,对eventpoller增加releasePool,方便外部调用者在适当的时候主动释放所有的eventloop,从而避免卡死的问题。
其他
关于底层锁住的原因参考https://github.com/ZLMediaKit/ZLMediaKit/issues/4580中的讨论