Bugfix on watchdogs.py, remove type hints because of wheezy and jessie

SoftwareWatchdog did not restart after daemon reload and switching from 0 to >=1 value
ResetDriver trigger will not always return True if not_implemented is True
This commit is contained in:
2020-05-02 19:45:05 +02:00
parent beb073893b
commit a40b39eb22
6 changed files with 59 additions and 20 deletions

View File

@@ -1,6 +1,6 @@
<component name="InspectionProjectProfileManager"> <component name="InspectionProjectProfileManager">
<settings> <settings>
<option name="USE_PROJECT_PROFILE" value="false" /> <option name="PROJECT_PROFILE" value="wheezy" />
<version value="1.0" /> <version value="1.0" />
</settings> </settings>
</component> </component>

23
.idea/inspectionProfiles/wheezy.xml generated Normal file
View File

@@ -0,0 +1,23 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="wheezy" />
<inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ourVersions">
<value>
<list size="5">
<item index="0" class="java.lang.String" itemvalue="3.4" />
<item index="1" class="java.lang.String" itemvalue="3.5" />
<item index="2" class="java.lang.String" itemvalue="3.6" />
<item index="3" class="java.lang.String" itemvalue="3.7" />
<item index="4" class="java.lang.String" itemvalue="3.8" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="PyMandatoryEncodingInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myAllPythons" value="true" />
</inspection_tool>
<inspection_tool class="PyMissingOrEmptyDocstringInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PyMissingTypeHintsInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
</profile>
</component>

View File

@@ -120,7 +120,7 @@ def _zeroprocimg():
) )
def get_revpiled_address(configrsc_bytes: bytes) -> int: def get_revpiled_address(configrsc_bytes):
""" """
Find byte address of revpiled output. Find byte address of revpiled output.

View File

@@ -798,7 +798,9 @@ class RevPiPyLoad():
reset_driver_detected = pictory_reset_driver.triggered reset_driver_detected = pictory_reset_driver.triggered
# Dateiveränderungen prüfen mit beiden Funktionen! # Dateiveränderungen prüfen mit beiden Funktionen!
if reset_driver_detected and self.check_pictory_changed(): if (reset_driver_detected or
pictory_reset_driver.not_implemented) and \
self.check_pictory_changed():
file_changed = True file_changed = True
# Alle Verbindungen von ProcImgServer trennen # Alle Verbindungen von ProcImgServer trennen
@@ -830,9 +832,10 @@ class RevPiPyLoad():
# Kein psstart um Reload im Client zu erzeugen # Kein psstart um Reload im Client zu erzeugen
# Restart plc program after piCtory change # Restart plc program after piCtory change
if self.plc is not None and self.plc.is_alive() and ( if not pictory_reset_driver.not_implemented and \
self.reset_driver_action == 1 and file_changed or self.plc is not None and self.plc.is_alive() and (
self.reset_driver_action == 2 and reset_driver_detected): self.reset_driver_action == 2 and reset_driver_detected or
self.reset_driver_action == 1 and file_changed):
# Plc program is running and we have to restart it # Plc program is running and we have to restart it
proginit.logger.warning( proginit.logger.warning(
"restart plc program after 'reset driver' was requested" "restart plc program after 'reset driver' was requested"

View File

@@ -17,7 +17,7 @@ import proginit as pi
class SoftwareWatchdog: class SoftwareWatchdog:
def __init__(self, address: int, timeout: int, kill_process=None): def __init__(self, address, timeout, kill_process=None):
""" """
Software watchdog thread, which must be recreate if triggered. Software watchdog thread, which must be recreate if triggered.
@@ -29,6 +29,7 @@ class SoftwareWatchdog:
self._exit = Event() self._exit = Event()
self._ioctl_bytes = b'' self._ioctl_bytes = b''
self._process = None self._process = None
self._stopped = False
self._timeout = 0.0 self._timeout = 0.0
self.triggered = False self.triggered = False
@@ -85,6 +86,7 @@ class SoftwareWatchdog:
def reset(self): def reset(self):
"""Reset watchdog functions after triggered or stopped.""" """Reset watchdog functions after triggered or stopped."""
pi.logger.debug("enter SoftwareWatchdog.reset()") pi.logger.debug("enter SoftwareWatchdog.reset()")
self._stopped = False
self._exit.clear() self._exit.clear()
self.triggered = False self.triggered = False
@@ -96,18 +98,19 @@ class SoftwareWatchdog:
def stop(self): def stop(self):
"""Shut down watchdog task and wait for exit.""" """Shut down watchdog task and wait for exit."""
pi.logger.debug("enter SoftwareWatchdog.stop()") pi.logger.debug("enter SoftwareWatchdog.stop()")
self._stopped = True
self._exit.set() self._exit.set()
if self.__th.is_alive(): if self.__th.is_alive():
self.__th.join() self.__th.join()
pi.logger.debug("leave SoftwareWatchdog.stop()") pi.logger.debug("leave SoftwareWatchdog.stop()")
@property @property
def address(self) -> int: def address(self):
"""Byte address of RevPiLED byte.""" """Byte address of RevPiLED byte."""
return unpack("<Hxx", self._ioctl_bytes)[0] return unpack("<Hxx", self._ioctl_bytes)[0]
@address.setter @address.setter
def address(self, value: int) -> None: def address(self, value):
"""Byte address of RevPiLED byte.""" """Byte address of RevPiLED byte."""
if not isinstance(value, int): if not isinstance(value, int):
raise TypeError("address must be <class 'int'>") raise TypeError("address must be <class 'int'>")
@@ -120,22 +123,22 @@ class SoftwareWatchdog:
pi.logger.debug("set software watchdog address to {0}".format(value)) pi.logger.debug("set software watchdog address to {0}".format(value))
@property @property
def kill_process(self) -> Popen: def kill_process(self):
return self._process return self._process
@kill_process.setter @kill_process.setter
def kill_process(self, value: Popen) -> None: def kill_process(self, value):
if not (value is None or isinstance(value, Popen)): if not (value is None or isinstance(value, Popen)):
raise TypeError("kill_process must be <class 'subprocess.Popen'>") raise TypeError("kill_process must be <class 'subprocess.Popen'>")
self._process = value self._process = value
@property @property
def timeout(self) -> int: def timeout(self):
"""Timeout to trigger watchdog on no change of bit.""" """Timeout to trigger watchdog on no change of bit."""
return int(self._timeout) return int(self._timeout)
@timeout.setter @timeout.setter
def timeout(self, value: int): def timeout(self, value):
""" """
Timeout to trigger watchdog on no change of bit. Timeout to trigger watchdog on no change of bit.
@@ -150,12 +153,17 @@ class SoftwareWatchdog:
if value == 0: if value == 0:
# A value of 0 will stop the watchdog thread # A value of 0 will stop the watchdog thread
self.stop() self._exit.set()
if self.__th.is_alive():
self.__th.join()
# Set after exit thread to not trigger watchdog
self._timeout = 0.0 self._timeout = 0.0
else: else:
self._timeout = float(value) self._timeout = float(value)
if not (self.triggered or if not (self.triggered or
self._exit.is_set() or self.__th.is_alive()): self._stopped or self.__th.is_alive()):
self._exit.clear()
self.__th = Thread(target=self.__th_run) self.__th = Thread(target=self.__th_run)
self.__th.start() self.__th.start()
pi.logger.debug( pi.logger.debug(
@@ -172,10 +180,12 @@ class ResetDriverWatchdog(Thread):
self.daemon = True self.daemon = True
self._exit = False self._exit = False
self._fh = None self._fh = None
self.not_implemented = False
"""True, if KB_WAIT_FOR_EVENT is not implemented in piControl."""
self._triggered = False self._triggered = False
self.start() self.start()
def run(self) -> None: def run(self):
""" """
Mainloop of watchdog for reset_driver. Mainloop of watchdog for reset_driver.
@@ -188,6 +198,7 @@ class ResetDriverWatchdog(Thread):
try: try:
self._fh = os.open(pi.pargs.procimg, os.O_RDONLY) self._fh = os.open(pi.pargs.procimg, os.O_RDONLY)
except Exception: except Exception:
self.not_implemented = True
pi.logger.error( pi.logger.error(
"can not open process image at '{0}' for piCtory " "can not open process image at '{0}' for piCtory "
"reset_driver watchdog".format(pi.pargs.procimg) "reset_driver watchdog".format(pi.pargs.procimg)
@@ -203,6 +214,7 @@ class ResetDriverWatchdog(Thread):
self._triggered = True self._triggered = True
pi.logger.debug("piCtory reset_driver detected") pi.logger.debug("piCtory reset_driver detected")
except Exception: except Exception:
self.not_implemented = True
os.close(self._fh) os.close(self._fh)
self._fh = None self._fh = None
pi.logger.warning("IOCTL KB_WAIT_FOR_EVENT is not implemented") pi.logger.warning("IOCTL KB_WAIT_FOR_EVENT is not implemented")
@@ -210,7 +222,7 @@ class ResetDriverWatchdog(Thread):
pi.logger.debug("leave ResetDriverWatchdog.run()") pi.logger.debug("leave ResetDriverWatchdog.run()")
def stop(self) -> None: def stop(self):
"""Stop watchdog for piCtory reset_driver.""" """Stop watchdog for piCtory reset_driver."""
pi.logger.debug("enter ResetDriverWatchdog.stop()") pi.logger.debug("enter ResetDriverWatchdog.stop()")
@@ -222,7 +234,8 @@ class ResetDriverWatchdog(Thread):
pi.logger.debug("leave ResetDriverWatchdog.stop()") pi.logger.debug("leave ResetDriverWatchdog.stop()")
@property @property
def triggered(self) -> bool: def triggered(self):
rc = self._triggered or not self.is_alive() """Will return True one time after watchdog was triggered."""
rc = self._triggered
self._triggered = False self._triggered = False
return rc return rc

View File

@@ -27,7 +27,7 @@ setup(
license="LGPLv3", license="LGPLv3",
name="revpipyload", name="revpipyload",
version="0.8.5", version="0.8.5d",
scripts=["data/revpipyload"], scripts=["data/revpipyload"],