# HG changeset patch # User Edouard Tisserant # Date 1554807935 -7200 # Node ID e172ab28d04e5522220d8168eda9e8583c160ab9 # Parent 8f0d6c5fd55fca52acb165302a4b77701393b31d Continue fixing deadlock of previous commit, this time occuring when waiting for 'cleanup' python runtime call to finish. Now 'init' and 'cleanup' python runtime calls are called directly from main thread, and aren't anymore invoked in the context of wxMainloop and/or twisted reactor. diff -r 8f0d6c5fd55f -r e172ab28d04e runtime/PLCObject.py --- a/runtime/PLCObject.py Tue Apr 09 09:13:55 2019 +0200 +++ b/runtime/PLCObject.py Tue Apr 09 13:05:35 2019 +0200 @@ -42,6 +42,7 @@ from runtime.Stunnel import getPSKID from runtime import PlcStatus from runtime import MainWorker +from runtime import default_evaluator if os.name in ("nt", "ce"): dlopen = _ctypes.LoadLibrary @@ -319,13 +320,16 @@ return False - def PythonRuntimeCall(self, methodname): + def PythonRuntimeCall(self, methodname, use_evaluator=True): """ Calls init, start, stop or cleanup method provided by runtime python files, loaded when new PLC uploaded """ for method in self.python_runtime_vars.get("_runtime_%s" % methodname, []): - _res, exp = self.evaluator(method) + if use_evaluator: + _res, exp = self.evaluator(method) + else: + _res, exp = default_evaluator(method) if exp is not None: self.LogMessage(0, '\n'.join(traceback.format_exception(*exp))) @@ -379,6 +383,8 @@ self.LogMessage(0, traceback.format_exc()) raise + self.PythonRuntimeCall("init", use_evaluator=False) + self.PythonThreadCondLock = Lock() self.PythonThreadCond = Condition(self.PythonThreadCondLock) self.PythonThreadCmd = "Wait" @@ -391,6 +397,7 @@ if self.python_runtime_vars is not None: self.PythonThreadCommand("Finish") self.PythonThread.join() + self.PythonRuntimeCall("cleanup", use_evaluator=False) self.python_runtime_vars = None @@ -421,9 +428,6 @@ self.LogMessage(1, ('PyEval@0x%x(Code="%s") Exception "%s"') % (FBID, cmd, str(e))) def PythonThreadProc(self): - print('self.PythonRuntimeCall("init")') - self.PythonRuntimeCall("init") - while True: self.PythonThreadCondLock.acquire() cmd = self.PythonThreadCmd @@ -434,7 +438,6 @@ self.PythonThreadCondLock.release() if cmd == "Activate" : - print('self.PythonRuntimeCall("start")') self.PythonRuntimeCall("start") self.PythonThreadLoop() @@ -443,8 +446,6 @@ else: # "Finish" break - self.PythonRuntimeCall("cleanup") - def PythonThreadCommand(self, cmd): self.PythonThreadCondLock.acquire() self.PythonThreadCmd = cmd diff -r 8f0d6c5fd55f -r e172ab28d04e runtime/__init__.py --- a/runtime/__init__.py Tue Apr 09 09:13:55 2019 +0200 +++ b/runtime/__init__.py Tue Apr 09 13:05:35 2019 +0200 @@ -30,3 +30,13 @@ global _PLCObjectSingleton from runtime.PLCObject import PLCObject # noqa # pylint: disable=wrong-import-position _PLCObjectSingleton = PLCObject(*args, **kwargs) + + +def default_evaluator(tocall, *args, **kwargs): + try: + res = (tocall(*args, **kwargs), None) + except Exception: + res = (None, sys.exc_info()) + return res + +