# HG changeset patch # User Edouard Tisserant # Date 1555591343 -7200 # Node ID 9944a18cad17a9d65d8463f61dc16d8ad0cf99ec # Parent 46df689dbc3b3a80d12026a7cf2b19134ace349b# Parent 0615137bf515e27ad48bcb6c3540ea1a68101ee6 Merged fix_PLC_runtime_shutdown diff -r 46df689dbc3b -r 9944a18cad17 Beremiz_service.py --- a/Beremiz_service.py Tue Apr 16 14:45:41 2019 +0200 +++ b/Beremiz_service.py Thu Apr 18 14:42:23 2019 +0200 @@ -532,7 +532,8 @@ pyro_thread_started = Lock() pyro_thread_started.acquire() pyro_thread = Thread(target=pyroserver.PyroLoop, - kwargs=dict(when_ready=pyro_thread_started.release)) + kwargs=dict(when_ready=pyro_thread_started.release), + name="PyroThread") pyro_thread.start() # Wait for pyro thread to be effective @@ -557,7 +558,7 @@ else: ui_thread_target = app.MainLoop - ui_thread = Thread(target=ui_thread_target) + ui_thread = Thread(target=ui_thread_target, name="UIThread") ui_thread.start() # This order ui loop to unblock main thread when ready. @@ -581,6 +582,7 @@ pass pyroserver.Quit() +pyro_thread.join() plcobj = runtime.GetPLCObjectSingleton() plcobj.StopPLC() @@ -588,7 +590,9 @@ if havetwisted: reactor.stop() + ui_thread.join() elif havewx: app.ExitMainLoop() + ui_thread.join() sys.exit(0) diff -r 46df689dbc3b -r 9944a18cad17 ProjectController.py --- a/ProjectController.py Tue Apr 16 14:45:41 2019 +0200 +++ b/ProjectController.py Thu Apr 18 14:42:23 2019 +0200 @@ -1446,13 +1446,13 @@ def UpdateMethodsFromPLCStatus(self): updated = False - status = None + status = PlcStatus.Disconnected if self._connector is not None: PLCstatus = self._connector.GetPLCstatus() if PLCstatus is not None: status, log_count = PLCstatus self.UpdatePLCLog(log_count) - if status is None: + if status == PlcStatus.Disconnected: self._SetConnector(None, False) status = PlcStatus.Disconnected if self.previous_plcstate != status: diff -r 46df689dbc3b -r 9944a18cad17 images/Repair.png Binary file images/Repair.png has changed diff -r 46df689dbc3b -r 9944a18cad17 runtime/PLCObject.py --- a/runtime/PLCObject.py Tue Apr 16 14:45:41 2019 +0200 +++ b/runtime/PLCObject.py Thu Apr 18 14:42:23 2019 +0200 @@ -388,7 +388,7 @@ self.PythonThreadCondLock = Lock() self.PythonThreadCond = Condition(self.PythonThreadCondLock) self.PythonThreadCmd = "Wait" - self.PythonThread = Thread(target=self.PythonThreadProc) + self.PythonThread = Thread(target=self.PythonThreadProc, name="PLCPythonThread") self.PythonThread.start() # used internaly @@ -477,8 +477,14 @@ return True return False - @RunInMain def GetPLCstatus(self): + try: + return self._GetPLCstatus() + except EOFError: + return (PlcStatus.Disconnected, None) + + @RunInMain + def _GetPLCstatus(self): return self.PLCStatus, map(self.GetLogCount, xrange(LogLevelsCount)) @RunInMain @@ -645,7 +651,7 @@ def _TracesSwap(self): self.LastSwapTrace = time() if self.TraceThread is None and self.PLCStatus == PlcStatus.Started: - self.TraceThread = Thread(target=self.TraceThreadProc) + self.TraceThread = Thread(target=self.TraceThreadProc, name="PLCTrace") self.TraceThread.start() self.TraceLock.acquire() Traces = self.Traces diff -r 46df689dbc3b -r 9944a18cad17 runtime/PyroServer.py --- a/runtime/PyroServer.py Tue Apr 16 14:45:41 2019 +0200 +++ b/runtime/PyroServer.py Thu Apr 18 14:42:23 2019 +0200 @@ -12,6 +12,7 @@ from __future__ import absolute_import from __future__ import print_function import sys +import os import Pyro import Pyro.core as pyro @@ -27,6 +28,7 @@ self.ip_addr = ip_addr self.port = port self.servicepublisher = None + self.piper, self.pipew = None, None def _to_be_published(self): return self.servicename is not None and \ @@ -60,8 +62,11 @@ self.daemon.connect(pyro_obj, "PLCObject") when_ready() - self.daemon.requestLoop() - self.daemon.sock.close() + self.piper,self.pipew = os.pipe() + self.daemon.requestLoop(others=[self.piper], callback=lambda x:None) + self.piper, self.pipew = None, None + if hasattr(self,'sock'): + self.daemon.sock.close() self.Unpublish() def Restart(self): @@ -70,6 +75,9 @@ def Quit(self): self.continueloop = False self.daemon.shutdown(True) + self.daemon.closedown() + if self.pipew is not None: + os.write(self.pipew, "goodbye") def Publish(self): self.servicepublisher = ServicePublisher("PYRO") diff -r 46df689dbc3b -r 9944a18cad17 runtime/Worker.py --- a/runtime/Worker.py Tue Apr 16 14:45:41 2019 +0200 +++ b/runtime/Worker.py Thu Apr 18 14:42:23 2019 +0200 @@ -21,8 +21,9 @@ def __init__(self, call, *args, **kwargs): self.job = (call, args, kwargs) self.result = None - self.success = False + self.success = None self.exc_info = None + self.enabled = False def do(self): """ @@ -67,9 +68,11 @@ """ self._threadID = _thread.get_ident() self.mutex.acquire() + self.enabled = True if args or kwargs: _job = job(*args, **kwargs) _job.do() + # _job.success can't be None after do() if not _job.success: self.reraise(_job) @@ -99,6 +102,9 @@ else: # otherwise notify and wait for completion self.mutex.acquire() + if not self.enabled: + self.mutex.release() + raise EOFError("Worker is disabled") while self.job is not None: self.free.wait() @@ -110,6 +116,9 @@ self.free.notify() self.mutex.release() + if _job.success is None: + raise EOFError("Worker job was interrupted") + if _job.success: return _job.result else: @@ -122,6 +131,8 @@ # mark queue self._finish = True self.mutex.acquire() + self.enabled = False self.job = None self.todo.notify() + self.done.notify() self.mutex.release()