Browse Source

Fix stacktracer error

Yentl Van Tendeloo 6 years ago
parent
commit
5e501065c0
2 changed files with 104 additions and 2 deletions
  1. 102 0
      hybrid_server/stacktracer.py
  2. 2 2
      scripts/run_local_modelverse.py

+ 102 - 0
hybrid_server/stacktracer.py

@@ -0,0 +1,102 @@
+"""Stack tracer for multi-threaded applications.
+
+
+Usage:
+
+import stacktracer
+stacktracer.trace_start("trace.html",interval=5,auto=True) # Set auto flag to always update file!
+....
+stacktracer.stop_trace()
+"""
+
+
+
+import sys
+import traceback
+from pygments import highlight
+from pygments.lexers import PythonLexer
+from pygments.formatters import HtmlFormatter
+ 
+ # Taken from http://bzimmer.ziclix.com/2008/12/17/python-thread-dumps/
+ 
+def stacktraces():
+    code = []
+    for threadId, stack in sys._current_frames().items():
+        code.append("\n# ThreadID: %s" % threadId)
+        for filename, lineno, name, line in traceback.extract_stack(stack):
+            code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
+            if line:
+                code.append("  %s" % (line.strip()))
+ 
+    return highlight("\n".join(code), PythonLexer(), HtmlFormatter(
+      full=False,
+      # style="native",
+      noclasses=True,
+    ))
+
+
+# This part was made by nagylzs
+import os
+import time
+import threading
+
+class TraceDumper(threading.Thread):
+    """Dump stack traces into a given file periodically."""
+    def __init__(self,fpath,interval,auto):
+        """
+        @param fpath: File path to output HTML (stack trace file)
+        @param auto: Set flag (True) to update trace continuously.
+            Clear flag (False) to update only if file not exists.
+            (Then delete the file to force update.)
+        @param interval: In seconds: how often to update the trace file.
+        """
+        assert(interval>0.1)
+        self.auto = auto
+        self.interval = interval
+        self.fpath = os.path.abspath(fpath)
+        self.stop_requested = threading.Event()
+        threading.Thread.__init__(self)
+    
+    def run(self):
+        while not self.stop_requested.isSet():
+            time.sleep(self.interval)
+            if self.auto or not os.path.isfile(self.fpath):
+                self.stacktraces()
+    
+    def stop(self):
+        self.stop_requested.set()
+        self.join()
+        try:
+            if os.path.isfile(self.fpath):
+                os.unlink(self.fpath)
+        except:
+            pass
+    
+    def stacktraces(self):
+        fout = open(self.fpath,"wb+")
+        try:
+            fout.write(stacktraces())
+        finally:
+            fout.close()
+
+
+_tracer = None
+def trace_start(fpath,interval=5,auto=True):
+    """Start tracing into the given file."""
+    global _tracer
+    if _tracer is None:
+        _tracer = TraceDumper(fpath,interval,auto)
+        _tracer.setDaemon(True)
+        _tracer.start()
+    else:
+        return
+        #raise Exception("Already tracing to %s"%_tracer.fpath)
+
+def trace_stop():
+    """Stop tracing."""
+    global _tracer
+    if _tracer is None:
+        raise Exception("Not tracing, cannot stop.")
+    else:
+        _tracer.stop()
+        _tracer = None

+ 2 - 2
scripts/run_local_modelverse.py

@@ -31,8 +31,8 @@ try:
     sys.path.append(".")
     os.chdir("hybrid_server")
 
-    import stacktracer
-    stacktracer.trace_start("trace.html",interval=5,auto=True) # Set auto flag to always update file!
+    #import stacktracer
+    #stacktracer.trace_start("trace.html",interval=5,auto=True) # Set auto flag to always update file!
 
     import server
     import sccd.runtime.socket2event as socket2event