--- a/plugger.py Sun Jan 04 17:25:22 2009 +0100
+++ b/plugger.py Sun Jan 04 17:29:12 2009 +0100
@@ -700,6 +700,8 @@
+ self.DebugThread = None + self.debug_break = False # copy PluginMethods so that it can be later customized
self.PluginMethods = [dic.copy() for dic in self.PluginMethods]
@@ -1309,6 +1311,8 @@
self.logger.write_error("Build directory already clean\n")
self.ShowMethod("_showIECcode", False)
self.EnableMethod("_Clean", False)
self.CompareLocalAndRemotePLC()
############# Real PLC object access #############
@@ -1434,8 +1438,8 @@
# This lock is used to avoid flooding wx event stack calling callafter
self.DebugThreadSlowDownLock = Semaphore(0)
- while not _break and self._connector is not None:
+ self.debug_break = False + while (not self.debug_break) and (self._connector is not None): debug_tick, debug_vars = self._connector.GetTraceVariables()
#print debug_tick, debug_vars
self.IECdebug_lock.acquire()
@@ -1459,11 +1463,19 @@
wx.CallAfter(self.logger.write, "Debugger disabled\n")
+ self.debug_break = True self.IECdebug_lock.release()
wx.CallAfter(self.DebugThreadSlowDownLock.release)
self.DebugThreadSlowDownLock.acquire()
+ def KillDebugThread(self): + self.debug_break = True + self.DebugThreadSlowDownLock.release() + self.DebugThread.join(timeout=1) + if self.DebugThread.isAlive(): + self.logger.write_warning("Debug Thread couldn't be killed") + self.DebugThread = None @@ -1485,6 +1497,7 @@
self.logger.write_error("Couldn't start PLC debug !\n")
self.UpdateMethodsFromPLCStatus()
# def _Do_Test_Debug(self):
# self.temporary_non_weak_callable_refs = []
@@ -1506,6 +1519,10 @@
+ if self.DebugThread is not None: + self.logger.write("Stopping debug\n") if self._connector.StopPLC():
self.logger.write("Stopping PLC\n")
--- a/runtime/PLCObject.py Sun Jan 04 17:25:22 2009 +0100
+++ b/runtime/PLCObject.py Sun Jan 04 17:29:12 2009 +0100
@@ -61,6 +61,10 @@
self.CurrentPLCFilename=None
+ def StatusChange(self): + if self.statuschange is not None: + self.statuschange(self.PLCStatus) def _GetMD5FileName(self):
return os.path.join(self.workingdir, "lasttransferedPLC.md5")
@@ -169,21 +173,30 @@
def PythonThreadProc(self):
+ print "PythonThreadProc started" + my_globs = globals().copy() pyfile = os.path.join(self.workingdir, "runtime.py")
if os.path.exists(pyfile):
# TODO handle exceptions in runtime.py
- print "PythonThreadProc started"
+ # pyfile may redefine _runtime_cleanup + # or even call _PythonThreadProc itself. + execfile(pyfile, my_globs) + res,cmd = "None","None" while self.PLCStatus == "Started":
+ print "_PythonIterator(", res, ")", cmd = self._PythonIterator(res)
- #print "_PythonIterator(", res, ") -> ", cmd
+ res = str(eval(cmd,my_globs)) res = "#EXCEPTION : "+str(e)
- print "PythonThreadProc finished"
+ print "PythonThreadProc interrupted" + if my_globs.get("_runtime_cleanup",None) is not None: + my_globs["_runtime_cleanup"]() + print "PythonThreadProc cleaned up" def StartPLC(self, debug=False):
@@ -193,8 +206,7 @@
self.PLCStatus = "Started"
- if self.statuschange is not None:
- self.statuschange(self.PLCStatus)
self.PythonThread = Thread(target=self.PythonThreadProc)
self.PythonThread.start()
@@ -206,10 +218,12 @@
self.PLCStatus = "Stopped"
- if self.statuschange is not None:
- self.statuschange(self.PLCStatus)
+ self.PythonThread.join(timeout=1) + if self.PythonThread.isAlive(): + print "Python thread couldn't be killed" @@ -327,25 +341,27 @@
Return a list of variables, corresponding to the list of requiered idx
- tick = self._WaitDebugData()
- typename = ctypes.c_char_p()
- for given_idx in self._Idxs:
- buffer=self._IterDebugData(ctypes.byref(idx), ctypes.byref(typename))
- c_type,unpack_func = self.TypeTranslator.get(typename.value, (None,None))
- if c_type is not None and given_idx == idx.value:
- res.append(unpack_func(ctypes.cast(buffer,
- ctypes.POINTER(c_type)).contents))
- print "Debug error idx : %d, expected_idx %d, type : %s"%(idx.value, given_idx,typename.value)
+ if self.PLCStatus == "Started": + tick = self._WaitDebugData() + typename = ctypes.c_char_p() + for given_idx in self._Idxs: + buffer=self._IterDebugData(ctypes.byref(idx), ctypes.byref(typename)) + c_type,unpack_func = self.TypeTranslator.get(typename.value, (None,None)) + if c_type is not None and given_idx == idx.value: + res.append(unpack_func(ctypes.cast(buffer, + ctypes.POINTER(c_type)).contents)) + print "Debug error idx : %d, expected_idx %d, type : %s"%(idx.value, given_idx,typename.value) --- a/targets/plc_common_main.c Sun Jan 04 17:25:22 2009 +0100
+++ b/targets/plc_common_main.c Sun Jan 04 17:29:12 2009 +0100
@@ -69,6 +69,7 @@
@@ -79,6 +80,7 @@
--- a/targets/plc_python.c Sun Jan 04 17:25:22 2009 +0100
+++ b/targets/plc_python.c Sun Jan 04 17:29:12 2009 +0100
@@ -29,6 +29,7 @@
#define PYTHON_LOCKED_BY_PYTHON 0
#define PYTHON_LOCKED_BY_PLC 1
#define PYTHON_MUSTWAKEUP 2
+#define PYTHON_FINISHED 4 /* Each python_eval FunctionBlock have it own state */
@@ -55,6 +56,8 @@
+ PythonState = PYTHON_FINISHED; + UnBlockPythonCommands(); @@ -173,7 +176,10 @@
/* wait next FB to eval */
+ //printf("PythonIterator wait\n"); + if(PythonState & PYTHON_FINISHED) return NULL; /* Mark block as processing */