Skip to content

Conversation

@jeyawn
Copy link

@jeyawn jeyawn commented Dec 5, 2025

问题背景:

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中的讨论

@CLAassistant
Copy link

CLAassistant commented Dec 5, 2025

CLA assistant check
All committers have signed the CLA.

@xia-chu
Copy link
Member

xia-chu commented Dec 9, 2025

EventPollerPool是TaskExecutorGetterImp的子类,我觉得没必要重复定义releasePool()和releaseAllEventPoller()两个函数,只需要在TaskExecutorGetterImp基类实现一个release()函数就行了。

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

Successfully merging this pull request may close these issues.

3 participants