diff --git a/data/etc/revpipyload/revpipyload.conf b/data/etc/revpipyload/revpipyload.conf
index 01c99bd..71ed1ab 100644
--- a/data/etc/revpipyload/revpipyload.conf
+++ b/data/etc/revpipyload/revpipyload.conf
@@ -10,7 +10,7 @@ plcslave = 0
plcslaveacl =
plcslaveport = 55234
pythonversion = 3
-rtlevel = 1
+rtlevel = 0
xmlrpc = 0
xmlrpcacl =
zeroonerror = 0
diff --git a/doc/proginit.html b/doc/proginit.html
index 507669a..ecfaf75 100644
--- a/doc/proginit.html
+++ b/doc/proginit.html
@@ -23,6 +23,9 @@ Classes
Functions
+| _setuprt |
+Konfiguriert Programm fuer den RT-Scheduler. |
+
| _zeroprocimg |
Setzt Prozessabbild auf NULL. |
@@ -34,6 +37,24 @@ Functions
+
+_setuprt
+_setuprt(pid, evt_exit)
+
+Konfiguriert Programm fuer den RT-Scheduler.
+
+- pid
+-
+PID, der angehoben werden soll
+
+
+- Returns:
+-
+None
+
+
+
+
_zeroprocimg
_zeroprocimg()
diff --git a/eric-revpipyload.api b/eric-revpipyload.api
index 864e13a..2ebe052 100644
--- a/eric-revpipyload.api
+++ b/eric-revpipyload.api
@@ -31,6 +31,7 @@ procimgserver.ProcimgServer.start?4()
procimgserver.ProcimgServer.stop?4()
procimgserver.ProcimgServer.values?4()
procimgserver.ProcimgServer?1(xmlserver, aclmode)
+proginit._setuprt?5(pid, evt_exit)
proginit._zeroprocimg?5()
proginit.cleanup?4()
proginit.configure?4()
diff --git a/revpipyload.e4p b/revpipyload.e4p
index c895726..b18307f 100644
--- a/revpipyload.e4p
+++ b/revpipyload.e4p
@@ -1,7 +1,7 @@
-
+
en_US
diff --git a/revpipyload/plcsystem.py b/revpipyload/plcsystem.py
index d2a0037..eb8b867 100644
--- a/revpipyload/plcsystem.py
+++ b/revpipyload/plcsystem.py
@@ -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)
diff --git a/revpipyload/proginit.py b/revpipyload/proginit.py
index 0110be3..fe0b69e 100644
--- a/revpipyload/proginit.py
+++ b/revpipyload/proginit.py
@@ -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
diff --git a/revpipyload/revpipyload.py b/revpipyload/revpipyload.py
index 04e6fc8..245845a 100755
--- a/revpipyload/revpipyload.py
+++ b/revpipyload/revpipyload.py
@@ -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]",