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

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

если не удалось создать сокет и пробовал это делать каждые X секунд. По умолчанию 30 сек.
parent 0e7f1f7b
...@@ -202,6 +202,9 @@ namespace uniset ...@@ -202,6 +202,9 @@ namespace uniset
int port = conf->getArgPInt("--" + prefix + "-inet-port", it.getProp("iport"), 502); 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; mbinfo << myname << "(init): type=TCP inet=" << iaddr << " port=" << port << endl;
tcpserver = make_shared<ModbusTCPServerSlot>(iaddr, port); tcpserver = make_shared<ModbusTCPServerSlot>(iaddr, port);
...@@ -637,44 +640,68 @@ namespace uniset ...@@ -637,44 +640,68 @@ namespace uniset
mbinfo << myname << "(execute_tcp): run tcpserver (" mbinfo << myname << "(execute_tcp): run tcpserver ("
<< tcpserver->getInetAddress() << ":" << tcpserver->getInetPort() << tcpserver->getInetAddress() << ":" << tcpserver->getInetPort()
<< ")" << endl; << ")"
<< "["
<< " tcpBreakIfFailRun=" << tcpBreakIfFailRun
<< " tcpRepeatCreateSocketPause=" << tcpRepeatCreateSocketPause
<< "]"
<< endl;
tcpCancelled = false; tcpCancelled = false;
try while( isActive() && !tcpserver->isActive() )
{
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 )
{ {
mbcrit << myname << "(execute_tcp): Can`t create socket " try
<< tcpserver->getInetAddress() {
<< ":" << tcpserver->getInetPort() if( tcpserver->run( vaddr, true ) )
<< " err: " << e.displayText() << endl; break;
throw e;
} if( tcpBreakIfFailRun )
catch( const std::exception& e ) {
{ mbcrit << myname << "(execute_tcp): error run tcpserver: "
mbcrit << myname << "(execute_tcp): Can`t create socket " << tcpserver->getInetAddress()
<< tcpserver->getInetAddress() << ":" << tcpserver->getInetPort() << " err: not active.." << endl;
<< ":" << tcpserver->getInetPort() std::terminate();
<< " err: " << e.what() << endl; return;
throw e; }
} }
catch(...) catch( ModbusRTU::mbException& ex )
{ {
mbcrit << myname << "(execute_tcp): catch exception ... (" mbcrit << myname << "(execute_tcp): catch exception: "
<< tcpserver->getInetAddress() << tcpserver->getInetAddress()
<< ":" << tcpserver->getInetPort() << ":" << tcpserver->getInetPort() << " err: " << ex << endl;
<< endl; if( tcpBreakIfFailRun )
throw; 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; // tcpCancelled = true;
......
...@@ -304,6 +304,19 @@ namespace uniset ...@@ -304,6 +304,19 @@ namespace uniset
</MBTCPPersistentSlave> </MBTCPPersistentSlave>
\endcode \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 \section sec_MBSlave_REST_API MBSlave HTTP API
...@@ -646,6 +659,9 @@ namespace uniset ...@@ -646,6 +659,9 @@ namespace uniset
IOController::IOStateList::iterator sesscount_it; IOController::IOStateList::iterator sesscount_it;
std::atomic_bool tcpCancelled = { true }; std::atomic_bool tcpCancelled = { true };
bool tcpBreakIfFailRun = { false };
timeout_t tcpRepeatCreateSocketPause = { 30000 }; /*! пауза между попытками открыть сокет */
}; };
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
} // end of namespace uniset } // end of namespace uniset
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <ev++.h> #include <ev++.h>
#include <atomic> #include <atomic>
#include <thread> #include <thread>
#include <future>
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
namespace uniset namespace uniset
{ {
...@@ -32,7 +33,7 @@ namespace uniset ...@@ -32,7 +33,7 @@ namespace uniset
virtual void evprepare() {} virtual void evprepare() {}
// Управление потоком событий // Управление потоком событий
void evrun( bool thread = true ); bool evrun( bool thread = true );
void evstop(); void evstop();
ev::dynamic_loop loop; ev::dynamic_loop loop;
...@@ -40,7 +41,7 @@ namespace uniset ...@@ -40,7 +41,7 @@ namespace uniset
private: private:
void onStop() noexcept; void onStop() noexcept;
void defaultLoop() noexcept; void defaultLoop( std::promise<bool>& prepareOK ) noexcept;
std::atomic_bool cancelled = { false }; std::atomic_bool cancelled = { false };
std::atomic_bool isrunning = { false }; std::atomic_bool isrunning = { false };
......
...@@ -36,8 +36,9 @@ namespace uniset ...@@ -36,8 +36,9 @@ namespace uniset
/*! Запуск сервера /*! Запуск сервера
* \param thread - создавать ли отдельный поток * \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; virtual bool isActive() const override;
......
...@@ -81,15 +81,15 @@ namespace uniset ...@@ -81,15 +81,15 @@ namespace uniset
sessTimeout = msec; 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; vmbaddr = &_vmbaddr;
evrun(thread); return evrun(thread);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
bool ModbusTCPServer::isActive() const bool ModbusTCPServer::isActive() const
{ {
return evIsActive(); return evIsActive() && sock;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPServer::evprepare() void ModbusTCPServer::evprepare()
...@@ -103,14 +103,14 @@ namespace uniset ...@@ -103,14 +103,14 @@ namespace uniset
ostringstream err; ostringstream err;
err << "(ModbusTCPServer::evprepare): connect " << iaddr << ":" << port << " err: " << ex.what(); err << "(ModbusTCPServer::evprepare): connect " << iaddr << ":" << port << " err: " << ex.what();
dlog->crit() << err.str() << endl; dlog->crit() << err.str() << endl;
throw SystemError(err.str()); throw uniset::SystemError(err.str());
} }
catch( const std::exception& ex ) catch( const std::exception& ex )
{ {
ostringstream err; ostringstream err;
err << "(ModbusTCPServer::evprepare): connect " << iaddr << ":" << port << " err: " << ex.what(); err << "(ModbusTCPServer::evprepare): connect " << iaddr << ":" << port << " err: " << ex.what();
dlog->crit() << err.str() << endl; dlog->crit() << err.str() << endl;
throw SystemError(err.str()); throw uniset::SystemError(err.str());
} }
sock->setBlocking(false); sock->setBlocking(false);
......
...@@ -19,20 +19,34 @@ namespace uniset ...@@ -19,20 +19,34 @@ namespace uniset
evstop(); evstop();
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void EventLoopServer::evrun( bool thread ) bool EventLoopServer::evrun( bool thread )
{ {
if( isrunning ) if( isrunning )
return; return true;
isrunning = true; isrunning = true;
std::promise<bool> p;
auto prepareOK = p.get_future();
if( !thread ) if( !thread )
{ {
defaultLoop(); defaultLoop(p);
return; return prepareOK.get();
} }
else if( !thr ) 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 bool EventLoopServer::evIsActive() const noexcept
...@@ -67,22 +81,31 @@ namespace uniset ...@@ -67,22 +81,31 @@ namespace uniset
loop.break_loop(ev::ALL); loop.break_loop(ev::ALL);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void EventLoopServer::defaultLoop() noexcept void EventLoopServer::defaultLoop( std::promise<bool>& prepareOK ) noexcept
{ {
evterm.start(); evterm.start();
evprepare(); try
while( !cancelled )
{ {
try evprepare();
{ prepareOK.set_value(true);
loop.run(0);
} while( !cancelled )
catch( std::exception& ex )
{ {
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; 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