improve poller error handling
- repeated errors on poller are only once logged (per poll function / read_* method) - during exception handling, silent=True on a SECoP error indicates that the error is already logged + fix the name of HardwareError + add test for consistency of SECoPErrors + catch socket.timeout in AsynTcp Change-Id: I9df6c775cc19553b22a4d6e39591092adf7ff9a1 Reviewed-on: https://forge.frm2.tum.de/review/c/sine2020/secop/playground/+/28139 Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de> Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch> Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
This commit is contained in:
49
secop/io.py
49
secop/io.py
@ -31,8 +31,7 @@ import threading
|
||||
from secop.lib.asynconn import AsynConn, ConnectionClosed
|
||||
from secop.datatypes import ArrayOf, BLOBType, BoolType, FloatRange, IntRange, \
|
||||
StringType, TupleOf, ValueType
|
||||
from secop.errors import CommunicationFailedError, CommunicationSilentError, \
|
||||
ConfigError, ProgrammingError
|
||||
from secop.errors import CommunicationFailedError, ConfigError, ProgrammingError
|
||||
from secop.modules import Attached, Command, \
|
||||
Communicator, Done, Module, Parameter, Property
|
||||
from secop.lib import generalConfig
|
||||
@ -42,6 +41,10 @@ generalConfig.set_default('legacy_hasiodev', False)
|
||||
HEX_CODE = re.compile(r'[0-9a-fA-F][0-9a-fA-F]$')
|
||||
|
||||
|
||||
class SilentError(CommunicationFailedError):
|
||||
silent = True
|
||||
|
||||
|
||||
class HasIO(Module):
|
||||
"""Mixin for modules using a communicator"""
|
||||
io = Attached()
|
||||
@ -151,11 +154,10 @@ class IOBase(Communicator):
|
||||
self.callCallbacks()
|
||||
return Done
|
||||
except Exception as e:
|
||||
if str(e) == self._last_error:
|
||||
raise CommunicationSilentError(str(e)) from e
|
||||
self._last_error = str(e)
|
||||
self.log.error(self._last_error)
|
||||
raise
|
||||
if str(e) != self._last_error:
|
||||
self._last_error = str(e)
|
||||
self.log.error(self._last_error)
|
||||
raise SilentError(repr(e)) from e
|
||||
return Done
|
||||
|
||||
def write_is_connected(self, value):
|
||||
@ -249,10 +251,10 @@ class StringIO(IOBase):
|
||||
"""
|
||||
command = command.encode(self.encoding)
|
||||
if not self.is_connected:
|
||||
# do not try to reconnect here
|
||||
# read_is_connected is doing this when called by its poller
|
||||
self.read_is_connected() # try to reconnect
|
||||
if not self._conn:
|
||||
self.log.debug('can not connect to %r' % self.uri)
|
||||
raise CommunicationSilentError('can not connect to %r' % self.uri)
|
||||
raise SilentError('disconnected') from None
|
||||
try:
|
||||
with self._lock:
|
||||
# read garbage and wait before send
|
||||
@ -279,11 +281,12 @@ class StringIO(IOBase):
|
||||
self.comLog('< %s', reply)
|
||||
return reply
|
||||
except Exception as e:
|
||||
if str(e) == self._last_error:
|
||||
raise CommunicationSilentError(str(e)) from None
|
||||
self._last_error = str(e)
|
||||
self.log.error(self._last_error)
|
||||
raise
|
||||
if self._conn is None:
|
||||
raise SilentError('disconnected') from None
|
||||
if repr(e) != self._last_error:
|
||||
self._last_error = str(e)
|
||||
self.log.error(self._last_error)
|
||||
raise SilentError(repr(e)) from e
|
||||
|
||||
@Command(ArrayOf(StringType()), result=ArrayOf(StringType()))
|
||||
def multicomm(self, commands):
|
||||
@ -357,9 +360,10 @@ class BytesIO(IOBase):
|
||||
def communicate(self, request, replylen): # pylint: disable=arguments-differ
|
||||
"""send a request and receive (at least) <replylen> bytes as reply"""
|
||||
if not self.is_connected:
|
||||
# do not try to reconnect here
|
||||
# read_is_connected is doing this when called by its poller
|
||||
self.read_is_connected() # try to reconnect
|
||||
if not self._conn:
|
||||
raise CommunicationSilentError('can not connect to %r' % self.uri)
|
||||
raise SilentError('disconnected') from None
|
||||
try:
|
||||
with self._lock:
|
||||
# read garbage and wait before send
|
||||
@ -378,11 +382,12 @@ class BytesIO(IOBase):
|
||||
self.comLog('< %s', hexify(reply))
|
||||
return self.getFullReply(request, reply)
|
||||
except Exception as e:
|
||||
if str(e) == self._last_error:
|
||||
raise CommunicationSilentError(str(e)) from None
|
||||
self._last_error = str(e)
|
||||
self.log.error(self._last_error)
|
||||
raise
|
||||
if self._conn is None:
|
||||
raise SilentError('disconnected') from None
|
||||
if repr(e) != self._last_error:
|
||||
self._last_error = str(e)
|
||||
self.log.error(self._last_error)
|
||||
raise SilentError(repr(e)) from e
|
||||
|
||||
@Command((ArrayOf(TupleOf(BLOBType(), IntRange(0)))), result=ArrayOf(BLOBType()))
|
||||
def multicomm(self, requests):
|
||||
|
Reference in New Issue
Block a user