Commit 7589cb87 authored by Pavel Vainerman's avatar Pavel Vainerman

(MBSlave): сделал так, чтобы процесс не вылетал (по умолчанию)

если не удалось создать сокет и пробовал это делать каждые X секунд. По умолчанию 30 сек.
parent 0e7f1f7b
......@@ -202,6 +202,9 @@ namespace uniset
int port = conf->getArgPInt("--" + prefix + "-inet-port", it.getProp("iport"), 502);
tcpBreakIfFailRun = conf->getArgPInt("--" + prefix + "-break-if-fail-run", it.getProp("tcpBreakIfFailRun"), 0);
tcpRepeatCreateSocketPause = conf->getArgPInt("--" + prefix + "-repeat-create-socket", it.getProp("tcpRepeatCreateSocket"), 30000);
mbinfo << myname << "(init): type=TCP inet=" << iaddr << " port=" << port << endl;
tcpserver = make_shared<ModbusTCPServerSlot>(iaddr, port);
......@@ -637,44 +640,68 @@ namespace uniset
mbinfo << myname << "(execute_tcp): run tcpserver ("
<< tcpserver->getInetAddress() << ":" << tcpserver->getInetPort()
<< ")" << endl;
<< ")"
<< "["
<< " tcpBreakIfFailRun=" << tcpBreakIfFailRun
<< " tcpRepeatCreateSocketPause=" << tcpRepeatCreateSocketPause
<< "]"
<< endl;
tcpCancelled = false;
try
{
tcpserver->run( vaddr, true );
}
catch( ModbusRTU::mbException& ex )
{
mbcrit << myname << "(execute_tcp): catch excaption: "
<< tcpserver->getInetAddress()
<< ":" << tcpserver->getInetPort() << " err: " << ex << endl;
throw ex;
}
catch( const Poco::Net::NetException& e )
while( isActive() && !tcpserver->isActive() )
{
mbcrit << myname << "(execute_tcp): Can`t create socket "
<< tcpserver->getInetAddress()
<< ":" << tcpserver->getInetPort()
<< " err: " << e.displayText() << endl;
throw e;
}
catch( const std::exception& e )
{
mbcrit << myname << "(execute_tcp): Can`t create socket "
<< tcpserver->getInetAddress()
<< ":" << tcpserver->getInetPort()
<< " err: " << e.what() << endl;
throw e;
}
catch(...)
{
mbcrit << myname << "(execute_tcp): catch exception ... ("
<< tcpserver->getInetAddress()
<< ":" << tcpserver->getInetPort()
<< endl;
throw;
try
{
if( tcpserver->run( vaddr, true ) )
break;
if( tcpBreakIfFailRun )
{
mbcrit << myname << "(execute_tcp): error run tcpserver: "
<< tcpserver->getInetAddress()
<< ":" << tcpserver->getInetPort() << " err: not active.." << endl;
std::terminate();
return;
}
}
catch( ModbusRTU::mbException& ex )
{
mbcrit << myname << "(execute_tcp): catch exception: "
<< tcpserver->getInetAddress()
<< ":" << tcpserver->getInetPort() << " err: " << ex << endl;
if( tcpBreakIfFailRun )
throw ex;
}
catch( const Poco::Net::NetException& e )
{
mbcrit << myname << "(execute_tcp): Can`t create socket "
<< tcpserver->getInetAddress()
<< ":" << tcpserver->getInetPort()
<< " err: " << e.displayText() << endl;
if( tcpBreakIfFailRun )
throw e;
}
catch( const std::exception& e )
{
mbcrit << myname << "(execute_tcp): Can`t create socket "
<< tcpserver->getInetAddress()
<< ":" << tcpserver->getInetPort()
<< " err: " << e.what() << endl;
if( tcpBreakIfFailRun )
throw e;
}
catch(...)
{
mbcrit << myname << "(execute_tcp): catch exception ... ("
<< tcpserver->getInetAddress()
<< ":" << tcpserver->getInetPort()
<< endl;
if( tcpBreakIfFailRun )
throw;
}
msleep(tcpRepeatCreateSocketPause);
}
// tcpCancelled = true;
......
......@@ -304,6 +304,19 @@ namespace uniset
</MBTCPPersistentSlave>
\endcode
По умолчанию если не удалось создать сокет процесс пытается повторять попытки каждые
tcpRepeatCreateSocketPause и не вылетает. Но если задан параметр tcpBreakIfFailRun="1",
то процессы завершает работу после первой неудачной попытки.
Изменить эти параметры можно либо в конфигурационном файле:
\code
<MBTCPPersistentSlave ... tcpBreakIfFailRun="1" tcpRepeatCreateSocket="xxx msec"/>
\endcode
Либо аргументами командной строки:
- --prefix--break-if-fail-run 1
- --prefix-repeat-create-socket msec.
\section sec_MBSlave_REST_API MBSlave HTTP API
......@@ -646,6 +659,9 @@ namespace uniset
IOController::IOStateList::iterator sesscount_it;
std::atomic_bool tcpCancelled = { true };
bool tcpBreakIfFailRun = { false };
timeout_t tcpRepeatCreateSocketPause = { 30000 }; /*! пауза между попытками открыть сокет */
};
// --------------------------------------------------------------------------
} // end of namespace uniset
......
......@@ -5,6 +5,7 @@
#include <ev++.h>
#include <atomic>
#include <thread>
#include <future>
// -------------------------------------------------------------------------
namespace uniset
{
......@@ -32,7 +33,7 @@ namespace uniset
virtual void evprepare() {}
// Управление потоком событий
void evrun( bool thread = true );
bool evrun( bool thread = true );
void evstop();
ev::dynamic_loop loop;
......@@ -40,7 +41,7 @@ namespace uniset
private:
void onStop() noexcept;
void defaultLoop() noexcept;
void defaultLoop( std::promise<bool>& prepareOK ) noexcept;
std::atomic_bool cancelled = { false };
std::atomic_bool isrunning = { false };
......
......@@ -36,8 +36,9 @@ namespace uniset
/*! Запуск сервера
* \param thread - создавать ли отдельный поток
* \return TRUE - если поток успешно удалось запустить
*/
void run( const std::unordered_set<ModbusRTU::ModbusAddr>& vmbaddr, bool thread = false );
bool run( const std::unordered_set<ModbusRTU::ModbusAddr>& vmbaddr, bool thread = false );
virtual bool isActive() const override;
......
......@@ -81,15 +81,15 @@ namespace uniset
sessTimeout = msec;
}
// -------------------------------------------------------------------------
void ModbusTCPServer::run( const std::unordered_set<ModbusAddr>& _vmbaddr, bool thread )
bool ModbusTCPServer::run( const std::unordered_set<ModbusAddr>& _vmbaddr, bool thread )
{
vmbaddr = &_vmbaddr;
evrun(thread);
return evrun(thread);
}
// -------------------------------------------------------------------------
bool ModbusTCPServer::isActive() const
{
return evIsActive();
return evIsActive() && sock;
}
// -------------------------------------------------------------------------
void ModbusTCPServer::evprepare()
......@@ -103,14 +103,14 @@ namespace uniset
ostringstream err;
err << "(ModbusTCPServer::evprepare): connect " << iaddr << ":" << port << " err: " << ex.what();
dlog->crit() << err.str() << endl;
throw SystemError(err.str());
throw uniset::SystemError(err.str());
}
catch( const std::exception& ex )
{
ostringstream err;
err << "(ModbusTCPServer::evprepare): connect " << iaddr << ":" << port << " err: " << ex.what();
dlog->crit() << err.str() << endl;
throw SystemError(err.str());
throw uniset::SystemError(err.str());
}
sock->setBlocking(false);
......
......@@ -19,20 +19,34 @@ namespace uniset
evstop();
}
// ---------------------------------------------------------------------------
void EventLoopServer::evrun( bool thread )
bool EventLoopServer::evrun( bool thread )
{
if( isrunning )
return;
return true;
isrunning = true;
std::promise<bool> p;
auto prepareOK = p.get_future();
if( !thread )
{
defaultLoop();
return;
defaultLoop(p);
return prepareOK.get();
}
else if( !thr )
thr = make_shared<std::thread>( [ = ] { defaultLoop(); } );
thr = make_shared<std::thread>( [ &p, this ] { defaultLoop(std::ref(p)); } );
bool ret = prepareOK.get();
// если запуститься не удалось
if( !ret && thr )
{
thr->join();
thr = nullptr;
}
return ret;
}
// ---------------------------------------------------------------------------
bool EventLoopServer::evIsActive() const noexcept
......@@ -67,22 +81,31 @@ namespace uniset
loop.break_loop(ev::ALL);
}
// -------------------------------------------------------------------------
void EventLoopServer::defaultLoop() noexcept
void EventLoopServer::defaultLoop( std::promise<bool>& prepareOK ) noexcept
{
evterm.start();
evprepare();
while( !cancelled )
try
{
try
{
loop.run(0);
}
catch( std::exception& ex )
evprepare();
prepareOK.set_value(true);
while( !cancelled )
{
cerr << "(EventLoopServer::defaultLoop): " << ex.what() << endl;
try
{
loop.run(0);
}
catch( std::exception& ex )
{
cerr << "(EventLoopServer::defaultLoop): " << ex.what() << endl;
}
}
}
catch( std::exception& ex )
{
cerr << "(EventLoopServer::defaultLoop): " << ex.what() << endl;
prepareOK.set_value(false);
}
isrunning = false;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment