Making debugger more stable with LPC
authoredouard
Wed, 23 Feb 2011 16:54:29 +0100
changeset 578 6f5795bdee49
parent 577 04baf6607a44
child 579 554ba6df4ee0
Making debugger more stable with LPC
LPCBeremiz.py
connectors/LPC/LPCAppObject.py
connectors/LPC/LPCObject.py
plugger.py
--- a/LPCBeremiz.py	Tue Feb 22 14:11:50 2011 +0100
+++ b/LPCBeremiz.py	Wed Feb 23 16:54:29 2011 +0100
@@ -1122,8 +1122,11 @@
     """ Base class for file like objects to facilitate StdOut for the Shell."""
     def write(self, s, style = None):
         if s != '':
-            self.socket.send(s)
-        
+            self.socket.send(s.encode('utf8'))
+        
+    def writeyield(self, s):
+        self.write(s)
+
     def write_warning(self, s):
         self.write(s)
 
--- a/connectors/LPC/LPCAppObject.py	Tue Feb 22 14:11:50 2011 +0100
+++ b/connectors/LPC/LPCAppObject.py	Wed Feb 23 16:54:29 2011 +0100
@@ -106,11 +106,12 @@
                     buff += idxstr + forced_type_size_str + forcestr
                 else:
                     buff += idxstr + chr(0)
-            data = self.HandleSerialTransaction(
-                   SET_TRACE_VARIABLETransaction(buff))
         else:
+            buff = ""
             self._Idxs =  []
 
+        self.HandleSerialTransaction(SET_TRACE_VARIABLETransaction(buff))
+
     def GetTraceVariables(self):
         """
         Return a list of variables, corresponding to the list of required idx
@@ -143,5 +144,5 @@
             if offset and offset == size:
                 return self.PLCStatus, tick.value, res
             #PLCprint("Debug error - wrong buffer unpack !")
-        return self.PLCStatus, None, None
+        return self.PLCStatus, None, [] 
 
--- a/connectors/LPC/LPCObject.py	Tue Feb 22 14:11:50 2011 +0100
+++ b/connectors/LPC/LPCObject.py	Wed Feb 23 16:54:29 2011 +0100
@@ -45,12 +45,15 @@
             try:
                 self.PLCStatus, res = self.SerialConnection.HandleTransaction(transaction)
                 return res
+            except LPCProtoError,e:
+                self.pluginsroot.logger.write(_("PLC disconnected\n"))
+                if self.SerialConnection is not None:
+                    self.SerialConnection.close()
+                    self.SerialConnection = None
+                self.PLCStatus = "Disconnected"
+                return None
             except Exception,e:
                 self.pluginsroot.logger.write_warning(str(e)+"\n")
-                self.SerialConnection.close()
-                self.SerialConnection = None
-                self.PLCStatus = "Disconnected"
-                return None
         
     def StartPLC(self, debug=False):
         raise LPCProtoError("Not implemented")
--- a/plugger.py	Tue Feb 22 14:11:50 2011 +0100
+++ b/plugger.py	Wed Feb 23 16:54:29 2011 +0100
@@ -709,6 +709,9 @@
 
 MATIEC_ERROR_MODEL = re.compile(".*\.st:(\d+)-(\d+)\.\.(\d+)-(\d+): error : (.*)$")
 
+DEBUG_RETRIES_WARN = 3
+DEBUG_RETRIES_REREGISTER = 4
+
 class PluginsRoot(PlugTemplate, PLCControler):
     """
     This class define Root object of the plugin tree. 
@@ -1731,52 +1734,55 @@
         """
         This thread waid PLC debug data, and dispatch them to subscribers
         """
-        # This lock is used to avoid flooding wx event stack calling callafter
         self.debug_break = False
         debug_getvar_retry = 0
         while (not self.debug_break) and (self._connector is not None):
             plc_status, debug_tick, debug_vars = self._connector.GetTraceVariables()
+            debug_getvar_retry += 1
             #print debug_tick, debug_vars
-            self.IECdebug_lock.acquire()
-            if debug_vars is not None:
-                debug_getvar_retry = 0
+            if plc_status == "Started":
+                self.IECdebug_lock.acquire()
                 if len(debug_vars) == len(self.TracedIECPath):
+                    if debug_getvar_retry > DEBUG_RETRIES_WARN:
+                        wx.CallAfter(self.logger.write, 
+                                 _("... debugger recovered\n"))
+                    debug_getvar_retry = 0
                     for IECPath,value in zip(self.TracedIECPath, debug_vars):
                         if value is not None:
                             self.CallWeakcallables(IECPath, "NewValue", debug_tick, value)
                     self.CallWeakcallables("__tick__", "NewDataAvailable")
-                else :
-                    wx.CallAfter(self.logger.write_warning, 
-                                 _("Debug data do not match requested variable count %d != %d\n")%(len(debug_vars), len(self.TracedIECPath)))
-            else:
-                if plc_status == "Started":
-                    # Just in case, re-register debug registry to PLC
-                    if debug_getvar_retry == 0:
-                        wx.CallAfter(self.RegisterDebugVarToConnector)
-                        wx.CallAfter(self.logger.write_warning, 
-                                 _("Waiting debugger to recover...\n"))
-                    debug_getvar_retry += 1
+                self.IECdebug_lock.release()
+                if debug_getvar_retry == DEBUG_RETRIES_WARN:
+                    wx.CallAfter(self.logger.write, 
+                             _("Waiting debugger to recover...\n"))
+                if debug_getvar_retry == DEBUG_RETRIES_REREGISTER:
+                    # re-register debug registry to PLC
+                    wx.CallAfter(self.RegisterDebugVarToConnector)
+                if debug_getvar_retry != 0:
                     # Be patient, tollerate PLC to come up before debugging
                     time.sleep(0.1)
-                else:
-                    wx.CallAfter(self.logger.write, _("Debugger disabled\n"))
-                    self.debug_break = True
-            self.IECdebug_lock.release()
+            else:
+                self.debug_break = True
+        wx.CallAfter(self.logger.write, _("Debugger disabled\n"))
 
     def KillDebugThread(self):
         self.debug_break = True
         if self.DebugThread is not None:
-            self.DebugThread.join(timeout=1)
+            self.logger.writeyield(_("Stopping debug ... "))
+            self.DebugThread.join(timeout=5)
             if self.DebugThread.isAlive() and self.logger:
                 self.logger.write_warning(_("Debug Thread couldn't be killed"))
+            else:
+                self.logger.write(_("success\n"))
         self.DebugThread = None
 
     def _connect_debug(self): 
         if self.AppFrame:
             self.AppFrame.ResetGraphicViewers()
         self.RegisterDebugVarToConnector()
-        self.DebugThread = Thread(target=self.DebugThreadProc)
-        self.DebugThread.start()
+        if self.DebugThread is None:
+            self.DebugThread = Thread(target=self.DebugThreadProc)
+            self.DebugThread.start()
     
     def _Run(self):
         """
@@ -1815,9 +1821,7 @@
         if self._connector is not None and not self._connector.StopPLC():
             self.logger.write_error(_("Couldn't stop PLC !\n"))
 
-        if self.DebugThread is not None:
-            self.logger.write(_("Stopping debug\n"))
-            self.KillDebugThread()
+        self.KillDebugThread()
         
         self.UpdateMethodsFromPLCStatus()