My server start a Poco::Task which, in turn, start two TCPServer.
int TBServer::main(const std::vector<std::string>& args) {
if (!m_helpRequested) {
TaskManager tm;
tm.start(new ServerTask());
waitForTerminationRequest();
tm.cancelAll();
tm.joinAll();
}
return Application::EXIT_OK;
}
POCO_SERVER_MAIN(TBServer)
The Task is the following:
void ServerTask::runTask() {
AutoPtr<PropertyFileConfiguration> pConf;
try {
pConf = new PropertyFileConfiguration("TBServer.prop");
TCPServer local_svr();
TCPServer remote_svr();
local_svr.Start(pConf->getInt("local_svr_port", 5000));
UINT mode = pConf->getInt("svr_mode", 0);
// Socket mode
if (mode & 0x01)
remote_svr.Start(pConf->getInt("remote_svr_port", 8000));
while(!isCancelled())
{
// Do nothing here...the logic is inside the TCPServer classes
sleep(500);
}
}
catch (Poco::Exception e) {
log << e.message() << std::endl;
}
}
The TCPServe class here is a simple wrapper around Poco::Net::TCPServer.
The problem here is that, when I close the application, I get an access violation, maybe due to terminate the TCPServer and TCPConnection in a wrong way.
This is the call stack:
ntdll.dll!_RtlpWaitForCriticalSection@4() + 0x5b byte
ntdll.dll!_RtlEnterCriticalSection@4() + 0x46 byte
> TBServer.exe!Poco::MutexImpl::lockImpl() Riga 76 + 0xc byte C++
TBServer.exe!Poco::FastMutex::lock() Riga 260 C++
TBServer.exe!Poco::Net::TCPServerDispatcher::release() Riga 113 C++
TBServer.exe!Poco::Net::TCPServer::~TCPServer() Riga 75 C++
TBServer.exe!Poco::Net::TCPServer::`scalar deleting destructor'() + 0x2b byte C++
TBServer.exe!TCPServer::~TCPServer() Line 86 + 0x37 byte C++
TBServer.exe!TCPServer::`scalar deleting destructor'() + 0x2b byte C++
TBServer.exe!Poco::ReleasePolicy<Poco::Net::TCPServerConnectionFactory>::release(Poco::Net::TCPServerConnectionFactory * pObj=0x0141fa8c) Line 90 + 0x34 byte C++
TBServer.exe!Poco::SharedPtr<Poco::Net::TCPServerConnectionFactory,Poco::ReferenceCounter,Poco::ReleasePolicy<Poco::Net::TCPServerConnectionFactory> >::release() Line 404 + 0xc byte C++
TBServer.exe!Poco::SharedPtr<Poco::Net::TCPServerConnectionFactory,Poco::ReferenceCounter,Poco::ReleasePolicy<Poco::Net::TCPServerConnectionFactory> >::~SharedPtr<Poco::Net::TCPServerConnectionFactory,Poco::ReferenceCounter,Poco::ReleasePolicy<Poco::Net::TCPServerConnectionFactory> >() Line 160 C++
TBServer.exe!Poco::Net::TCPServerDispatcher::~TCPServerDispatcher() Line 99 + 0x1a byte C++
TBServer.exe!Poco::Net::TCPServerDispatcher::`scalar deleting destructor'() + 0x2b byte C++
TBServer.exe!Poco::Net::TCPServerDispatcher::release() Line 115 + 0x3a byte C++
TBServer.exe!Poco::Net::TCPServer::~TCPServer() Line 75 C++
TBServer.exe!Poco::Net::TCPServer::`scalar deleting destructor'() + 0x2b byte C++
TBServer.exe!TCPServer::~TCPServer() Line 86 + 0x37 byte C++
TBServer.exe!ServerTask::runTask() Line 114 + 0xf byte C++
TBServer.exe!Poco::Task::run() Line 85 + 0xf byte C++
TBServer.exe!Poco::PooledThread::run() Line 215 + 0x15 byte C++
TBServer.exe!Poco::ThreadImpl::runnableEntry(void * pThread=0x0122089c) Line 245 + 0x13 byte C++
If someone would check this situation I prepared a little project which demonstrates the issue. It can be found here
You'll need to call Poco::Net::TCPServer::stop on your instances of this type before exiting the scope of your function, otherwise they won't destruct properly - and you get the diagnostic you posted.
Note: Since you already have a wrapper, place a call to wrapped_server.stop () in the destructor of that type to handle it automatically.
Inside Poco::Net::TCPServer::start a new thread is created that waits for, and accepts, incoming connections, and that thread needs time to clean-up after itself.
By just calling the destructor, without calling .stop, this other thread will try to access memory that is no longer available.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With