Commit 04405ecf authored by Pavel Vainerman's avatar Pavel Vainerman

(ModbusTCPMaster): правки в обработке disconnect

(UTCPStream): сделал shutdown перед close (для корректного завершения соединения), добавил проверку на POCO_INVALID_SOCKET (SM): сделал чтобы SM вылетала в случае если настал activateTimeout.
parent b9994862
......@@ -14,7 +14,7 @@
Name: libuniset2
Version: 2.5
Release: alt14
Release: alt14.4
Summary: UniSet - library for building distributed industrial control systems
License: LGPL
......@@ -486,6 +486,18 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname
# ..
%changelog
* Tue Sep 20 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt14.4
- UTCPStream: check POCO_INVALID_SOCKET
* Mon Sep 19 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt14.3
- UTCPStream: shudown and close (for disconnect)
* Mon Sep 19 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt14.2
- (ModbusTCPMaster): added disconnect() function
* Mon Sep 19 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt14.1
- (ModbusTCPMaster): added catch exceptions
* Mon Sep 12 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt14
- up build
......
......@@ -124,6 +124,47 @@ TEST_CASE("MBTCPMaster: reconnect", "[modbus][mbmaster][mbtcpmaster]")
REQUIRE_FALSE(mb.isConnection());
}
// -----------------------------------------------------------------------------
TEST_CASE("MBTCPMaster: forceDisconnect", "[modbus][mbmaster][mbtcpmaster][forceDisconnect]")
{
InitTest();
ModbusTCPMaster mb;
mb.setTimeout(500);
for( size_t i=0; i<1000; i++ )
{
// подключение к несуществующему адресу
REQUIRE_FALSE(mb.connect(iaddr, 2048));
try
{
mb.read03(slaveADDR,10,1);
}
catch(...){}
REQUIRE_FALSE(mb.isConnection());
mb.forceDisconnect();
}
}
// -----------------------------------------------------------------------------
TEST_CASE("MBTCPMaster: disconnect", "[modbus][mbmaster][mbtcpmaster][disconnect]")
{
InitTest();
ModbusTCPMaster mb;
mb.setTimeout(500);
mb.setForceDisconnect(true);
for( size_t i=0; i<1000; i++ )
{
// подключение к несуществующему адресу
REQUIRE_FALSE(mb.connect(iaddr, 2048));
try
{
mb.read03(slaveADDR,10,1);
}
catch(...){}
REQUIRE_FALSE(mb.isConnection());
mb.disconnect();
}
}
// -----------------------------------------------------------------------------
TEST_CASE("MBTCPMaster: 0x01 (read coil status)", "[modbus][0x01][mbmaster][mbtcpmaster]")
{
InitTest();
......
......@@ -69,8 +69,6 @@ SharedMemory::SharedMemory( ObjectId id, const std::string& datafile, const std:
msecPulsar(0),
confnode(0)
{
mutex_start.setName(myname + "_mutex_start");
auto conf = uniset_conf();
string cname(confname);
......@@ -155,7 +153,7 @@ SharedMemory::SharedMemory( ObjectId id, const std::string& datafile, const std:
evntPause = conf->getArgPInt("--e-startup-pause", 5000);
activateTimeout = conf->getArgPInt("--activate-timeout", 30000);
activateTimeout = conf->getArgPInt("--activate-timeout", 60000);
sidPulsar = DefaultObjectId;
string p = conf->getArgParam("--pulsar-id", it.getProp("pulsar_id"));
......@@ -197,17 +195,21 @@ SharedMemory::~SharedMemory()
void SharedMemory::timerInfo( const TimerMessage* tm )
{
if( tm->id == tmHeartBeatCheck )
{
checkHeartBeat();
}
else if( tm->id == tmEvent )
{
workready = 1;
workready = true;
// рассылаем уведомление, о том, чтобы стартанули
SystemMessage sm1(SystemMessage::WatchDog);
sendEvent(sm1);
askTimer(tm->id, 0);
}
else if( tm->id == tmHistory )
{
saveToHistory();
}
else if( tm->id == tmPulsar )
{
if( sidPulsar != DefaultObjectId )
......@@ -241,11 +243,14 @@ void SharedMemory::sysCommand( const SystemMessage* sm )
}
if( !activated )
smcrit << myname << "(sysCommand): ************* don`t activate?! ************" << endl;
{
smcrit << myname << "(sysCommand): Don`t activate! TERMINATE.." << endl;
std::terminate();
}
// подождать пока пройдёт инициализация
// см. activateObject()
UniSetTypes::uniset_rwmutex_rlock l(mutex_start);
std::unique_lock<std::mutex> lock(mutexStart);
askTimer(tmHeartBeatCheck, heartbeatCheckTime);
askTimer(tmEvent, evntPause, 1);
......@@ -294,7 +299,7 @@ bool SharedMemory::activateObject()
{
activated = false;
UniSetTypes::uniset_rwmutex_wrlock l(mutex_start);
std::unique_lock<std::mutex> lock(mutexStart);
res = IONotifyController::activateObject();
// инициализируем указатели
......@@ -328,6 +333,7 @@ bool SharedMemory::activateObject()
}
cout << myname << ": ********** activate: " << pt.getCurrent() << " msec " << endl;
sminfo << myname << ": ********** activate: " << pt.getCurrent() << " msec " << endl;
return res;
}
// ------------------------------------------------------------------------------------------
......
......@@ -417,7 +417,7 @@ class SharedMemory:
void buildEventList( xmlNode* cnode );
void readEventList( const std::string& oname );
UniSetTypes::uniset_rwmutex mutex_start;
std::mutex mutexStart;
class HeartBeatInfo
{
......
......@@ -44,6 +44,7 @@ class UTCPStream:
bool isSetLinger() const;
void forceDisconnect(); // disconnect() без ожидания (с отключением SO_LINGER)
void disconnect();
// --------------------------------------------------------------------
int getSocket() const;
......
......@@ -59,7 +59,7 @@ void ModbusTCPMaster::setChannelTimeout( timeout_t msec )
Poco::Timespan tm = UniSetTimer::millisecToPoco(msec);
Poco::Timespan old = tcp->getReceiveTimeout();;
if( old.microseconds() == tm.microseconds() )
if( old.totalMicroseconds() == tm.totalMicroseconds() )
return;
tcp->setReceiveTimeout(tm);
......@@ -201,6 +201,7 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
}
cleanInputStream();
if( tcp )
tcp->forceDisconnect();
return erTimeOut; // return erHardwareError;
}
......@@ -247,12 +248,13 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
if( force_disconnect )
{
if( dlog->is_info() )
dlog->info() << "(query): force disconnect.." << endl;
dlog->info() << "(query): disconnect.." << endl;
// при штатном обмене..лучше дождаться конца "посылки"..
// поэтому применяем disconnect(), а не forceDisconnect()
// (с учётом выставленной опции setLinger(true))
tcp->close();
if( tcp )
tcp->disconnect();
}
return res;
......@@ -267,6 +269,7 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
dlog->info() << "(query): force disconnect.." << endl;
// cleanInputStream();
if( tcp )
tcp->forceDisconnect();
}
......@@ -303,7 +306,7 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
catch( const std::exception& e )
{
if( dlog->is_warn() )
dlog->crit() << "(query): " << e.what() << std::endl;
dlog->warn() << "(query): " << e.what() << std::endl;
}
return erTimeOut; // erHardwareError
......@@ -385,7 +388,7 @@ bool ModbusTCPMaster::connect( const std::string& addr, int _port, bool closeOld
{
ostringstream s;
s << "(ModbusTCPMaster): connect " << iaddr << ":" << port << " error: " << e.what();
dlog->crit() << iaddr << std::endl;
dlog->crit() << s.str() << std::endl;
}
}
......@@ -426,13 +429,22 @@ bool ModbusTCPMaster::connect( const Poco::Net::SocketAddress& addr, int _port,
tcp->setNoDelay(true);
return true;
}
catch( Poco::TimeoutException& ex)
{
if( dlog->debugging(Debug::CRIT) )
{
ostringstream s;
s << "(ModbusTCPMaster): create connection " << iaddr << ":" << port << " timeout exception";
dlog->crit() << s.str() << std::endl;
}
}
catch( Poco::Net::NetException& ex)
{
if( dlog->debugging(Debug::CRIT) )
{
ostringstream s;
s << "(ModbusTCPMaster): create connection " << iaddr << ":" << port << " error: " << ex.displayText();
dlog->crit() << iaddr << std::endl;
dlog->crit() << s.str() << std::endl;
}
}
catch( const std::exception& e )
......@@ -441,7 +453,7 @@ bool ModbusTCPMaster::connect( const Poco::Net::SocketAddress& addr, int _port,
{
ostringstream s;
s << "(ModbusTCPMaster): connection " << iaddr << ":" << port << " error: " << e.what();
dlog->crit() << iaddr << std::endl;
dlog->crit() << s.str() << std::endl;
}
}
catch( ... )
......@@ -466,7 +478,7 @@ void ModbusTCPMaster::disconnect()
if( !tcp )
return;
tcp->close();
tcp->disconnect(); // close();
tcp = nullptr;
}
// -------------------------------------------------------------------------
......
......@@ -76,7 +76,7 @@ void TCPCheck::check_thread()
t.create(ip, port, tout_msec);
t.setKeepAliveParams( (tout_msec > 1000 ? tout_msec / 1000 : 1) );
setResult(true);
t.close();
t.disconnect();
}
catch( ... ) {}
}
......
......@@ -5,7 +5,11 @@ using namespace std;
// -------------------------------------------------------------------------
USocket::~USocket()
{
try
{
close();
}
catch(...){}
}
// -------------------------------------------------------------------------
USocket::USocket( int sock )
......
......@@ -12,7 +12,11 @@ using namespace std;
// -------------------------------------------------------------------------
UTCPSocket::~UTCPSocket()
{
try
{
Poco::Net::ServerSocket::close();
}
catch(...){}
}
// -------------------------------------------------------------------------
UTCPSocket::UTCPSocket()
......
......@@ -57,20 +57,40 @@ bool UTCPStream::isSetLinger() const
// -------------------------------------------------------------------------
void UTCPStream::forceDisconnect()
{
if( !isConnected() )
return;
try
{
bool on;
int sec;
Poco::Net::StreamSocket::getLinger(on, sec);
setLinger(false, 0);
}
// catch( Poco::Net::NetException& ex ){}
catch( std::exception& ex ){}
try
{
close();
//shutdown();
Poco::Net::StreamSocket::setLinger(on, sec);
}
catch( Poco::Net::NetException& )
// catch( Poco::Net::NetException& ex ){}
catch( std::exception& ex ){}
}
// -------------------------------------------------------------------------
void UTCPStream::disconnect()
{
try
{
shutdown();
}
// catch( Poco::Net::NetException& ex ){}
catch( std::exception& ex ){}
try
{
close();
}
// catch( Poco::Net::NetException& ex ){}
catch( std::exception& ex ){}
}
// -------------------------------------------------------------------------
int UTCPStream::getSocket() const
......@@ -81,13 +101,13 @@ int UTCPStream::getSocket() const
timeout_t UTCPStream::getTimeout() const
{
auto tm = Poco::Net::StreamSocket::getReceiveTimeout();
return tm.microseconds();
return tm.totalMicroseconds();
}
// -------------------------------------------------------------------------
void UTCPStream::create(const std::string& hname, int port, timeout_t tout_msec )
void UTCPStream::create( const std::string& hname, int port, timeout_t tout_msec )
{
Poco::Net::SocketAddress sa(hname, port);
connect(sa, tout_msec * 1000);
Poco::Net::SocketAddress saddr(hname, port);
connect(saddr, UniSetTimer::millisecToPoco(tout_msec));
setKeepAlive(true);
Poco::Net::StreamSocket::setLinger(true, 1);
setKeepAliveParams();
......@@ -95,7 +115,7 @@ void UTCPStream::create(const std::string& hname, int port, timeout_t tout_msec
// -------------------------------------------------------------------------
bool UTCPStream::isConnected() noexcept
{
return ( Poco::Net::StreamSocket::sockfd() > 0 );
return ( Poco::Net::StreamSocket::sockfd() != POCO_INVALID_SOCKET );
/*
try
{
......
......@@ -132,8 +132,7 @@ void LogReader::disconnect()
try
{
//tcp->shutdown();
tcp->close();
tcp->disconnect();
}
catch( const Poco::Net::NetException& e )
{
......
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