Skip to content
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

communicator无法正常terminate #313

Open
emiyalee opened this issue Nov 18, 2024 · 0 comments
Open

communicator无法正常terminate #313

emiyalee opened this issue Nov 18, 2024 · 0 comments

Comments

@emiyalee
Copy link

communicator调用terminate方法时,会加一个递归锁,

void Communicator::terminate()
{
    {
        if (_terminating)
            return;

        TC_LockT<TC_ThreadRecMutex> lock(_recMutex);

        _terminating = true;
        
        TC_Port::unregisterCtrlC(_sigId);

        if (_initialized)
        {
            //先要结束stat的, 这样后续结束可以把stat队列清空
			if (_statReport)
			{
				_statReport->terminate();

                if(_statReport->joinable())
                {
                    _statReport->join();
                }
			}

            for (size_t i = 0; i < _communicatorEpoll.size(); ++i)
            {
            	if(_communicatorEpoll[i]) {
		            _communicatorEpoll[i]->terminate();
                }
            }

...

然后向网络线程的epoller对象注册一个同步操作,请求回调CommunicatorEpoll::handleTerminate方法。

void CommunicatorEpoll::notifyTerminate()
{
    if (_scheduler)
    {
        if(_threadId == this_thread::get_id())
        {
            //同一个线程里面结束, 直接释放相关资源即可
            CommunicatorEpoll::handleTerminate();
        }
        else
        {
            std::lock_guard<std::mutex> lock(_mutex);

            if (_scheduler)
            {
                //通知网络线程去释放资源!
                _epoller->syncCallback(std::bind(&CommunicatorEpoll::handleTerminate, this), 1000);

                // if (_scheduler)
                // {
                //     _epoller->syncCallback(std::bind(&CommunicatorEpoll::handleTerminate, this), 1000);
                //     LOG_CONSOLE_DEBUG << _scheduler.get() << endl;
                // }
            }
        }
    }
}

此时若接收到网络报文,在同一个epoller对象的回调中会通过Communicator::getStatReport()获取对象进行上报,在该函数内存也会加上述的同一把递归锁,

StatReport* Communicator::getStatReport()
{
    Communicator::initialize();

    return _statReport;
}

void Communicator::initialize()
{
    TC_LockT<TC_ThreadRecMutex> lock(_recMutex);

    //两次保护
    if (_initialized)
        return;

    _initialized = true;

    _sigId = TC_Port::registerCtrlC([&]{

		TC_Common::msleep(50);
		this->terminate();
#if TARGET_PLATFORM_WINDOWS
		ExitProcess(0);
#else
		exit(0);
#endif
	});

从而导致上述同步操作超时,最终没有调用CommunicatorEpoll::handleTerminate方法,程序会卡在terminate方法中,无法正常退出。

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

1 participant