Mit default zusammenführen

This commit is contained in:
2017-09-20 18:15:17 +02:00
7 changed files with 142 additions and 29 deletions

View File

@@ -11,6 +11,7 @@ import proginit
import shlex
import subprocess
from logsystem import PipeLogwriter
from proginit import _setuprt
from sys import stdout as sysstdout
from threading import Event, Thread
from time import sleep, asctime
@@ -41,7 +42,7 @@ class RevPiPlc(Thread):
self.exitcode = None
self.gid = 65534
self.uid = 65534
self.rtlevel = 1
self.rtlevel = 0
self.zeroonerror = False
self.zeroonexit = False
@@ -104,8 +105,16 @@ class RevPiPlc(Thread):
"""Fuehrt PLC-Programm aus und ueberwacht es."""
proginit.logger.debug("enter RevPiPlc.run()")
# LogWriter starten und Logausgaben schreiben
if self._plw is not None:
self._plw.logline("-" * 55)
self._plw.logline("plc: {} started: {}".format(
os.path.basename(self._program), asctime()
))
self._plw.start()
# Befehlstliste aufbauen
lst_proc = shlex.split("/usr/bin/env {} -OO -u {} {}".format(
lst_proc = shlex.split("/usr/bin/env {} -u {} {}".format(
"python2" if self._pversion == 2 else "python3",
self._program,
self._arguments
@@ -115,29 +124,13 @@ class RevPiPlc(Thread):
proginit.logger.info("start plc program {}".format(self._program))
self._procplc = self._spopen(lst_proc)
# RealTime Scheduler nutzen
if self.rtlevel > 0 and self._procplc.poll() is None:
proginit.logger.info(
"set scheduler profile of pid {}".format(self._procplc.pid)
)
ec = os.system("/usr/bin/env chrt -p {} {}".format(
20 if self.rtlevel == 2 else 1,
self._procplc.pid
))
if ec != 0:
proginit.logger.error(
"could not set scheduler profile of pid {}"
"".format(self._procplc.pid)
)
# LogWriter starten und Logausgaben schreiben
if self._plw is not None:
self._plw.logline("-" * 55)
self._plw.logline("plc: {} started: {}".format(
os.path.basename(self._program), asctime()
))
self._plw.start()
# RealTime Scheduler nutzen nach 5 Sekunden Programmvorlauf
if self.rtlevel > 0 \
and not self._evt_exit.wait(5) \
and self._procplc.poll() is None:
_setuprt(self._procplc.pid, self._evt_exit)
# Überwachung starten
while not self._evt_exit.is_set():
# Auswerten
@@ -179,7 +172,7 @@ class RevPiPlc(Thread):
else:
break
self._evt_exit.wait(1)
self._evt_exit.wait(0.5)
if self._plw is not None:
self._plw.logline("-" * 55)

View File

@@ -10,6 +10,7 @@ import logging
import os
import sys
from argparse import ArgumentParser
from subprocess import Popen, PIPE
forked = False
globalconffile = None
@@ -22,6 +23,99 @@ rapcatalog = None
startdir = None
def _setuprt(pid, evt_exit):
"""Konfiguriert Programm fuer den RT-Scheduler.
@param pid PID, der angehoben werden soll
@return None"""
if logger is not None:
logger.debug("enter _setuprt()")
dict_change = {
"ksoftirqd/0,ksoftirqd/1,ksoftirqd/2,ksoftirqd/3": 10,
"ktimersoftd/0,ktimersoftd/1,ktimersoftd/2,ktimersoftd/3": 20
}
for ps_change in dict_change:
# pid und prio ermitteln
kpidps = Popen([
"/bin/ps", "-o", "pid=,rtprio=", "-C", ps_change
], bufsize=1, stdout=PIPE)
# Timeout nachbilden da in Python 3.2 nicht vorhanden
count = 10
while kpidps.poll() is None:
count -= 1
if count == 0:
kpidps.kill()
if logger is not None:
logger.error(
"ps timeout to get rt prio info - no rt active"
)
return None
evt_exit.wait(0.5)
if evt_exit.is_set():
return None
try:
kpiddat = kpidps.communicate()[0]
lst_kpids = kpiddat.split()
except:
kpidps.kill()
if logger is not None:
logger.error(
"can not get pid and prio - no rt active"
)
return None
while len(lst_kpids) > 0:
# Elemente paarweise übernehmen
kpid = lst_kpids.pop(0)
kprio = lst_kpids.pop(0)
# Daten prüfen
if not kpid.isdigit():
if logger is not None:
logger.error(
"pid={} and prio={} are not valid - no rt active"
"".format(kpid, kprio)
)
return None
kpid = int(kpid)
# RTPrio ermitteln
if kprio.isdigit():
kprio = int(kprio)
else:
kprio = 0
if kprio < 10:
# Profile anpassen
ec = os.system("/usr/bin/env chrt -fp {} {}".format(
dict_change[ps_change], kpid
))
if ec != 0:
if logger is not None:
logger.error(
"could not adjust scheduler - no rt active"
)
return None
# SCHED_RR für pid setzen
if logger is not None:
logger.info("set scheduler profile of pid {}".format(pid))
ec = os.system("/usr/bin/env chrt -p 1 {}".format(pid))
if ec != 0 and logger is not None:
logger.error(
"could not set scheduler profile of pid {}"
"".format(pid)
)
if logger is not None:
logger.debug("leave _setuprt()")
def _zeroprocimg():
"""Setzt Prozessabbild auf NULL."""
procimg = "/dev/piControl0" if pargs is None else pargs.procimg

View File

@@ -165,7 +165,7 @@ class RevPiPyLoad():
self.pythonver = \
int(self.globalconfig["DEFAULT"].get("pythonversion", 3))
self.rtlevel = \
int(self.globalconfig["DEFAULT"].get("rtlevel", 1))
int(self.globalconfig["DEFAULT"].get("rtlevel", 0))
self.xmlrpc = \
int(self.globalconfig["DEFAULT"].get("xmlrpc", 0))
@@ -185,6 +185,10 @@ class RevPiPyLoad():
int(self.globalconfig["DEFAULT"].get("zeroonexit", 1))
# Workdirectory wechseln
if not os.access(self.plcworkdir, os.R_OK | os.W_OK | os.X_OK):
raise ValueError(
"can not access plcworkdir '{}'".format(self.plcworkdir)
)
os.chdir(self.plcworkdir)
# PLC Thread konfigurieren
@@ -666,7 +670,7 @@ class RevPiPyLoad():
"plcslaveacl": re_ipacl,
"plcslaveport": "[0-9]{,5}",
"pythonversion": "[23]",
"rtlevel": "[0-2]",
"rtlevel": "[0-1]",
"xmlrpc": "[0-3]",
"xmlrpcacl": re_ipacl,
"zeroonerror": "[01]",