diff options
author | Aldo Cortesi <aldo@nullcube.com> | 2016-06-11 19:52:24 +1200 |
---|---|---|
committer | Aldo Cortesi <aldo@nullcube.com> | 2016-06-11 19:52:24 +1200 |
commit | 09edbd9492e59c0c8dcae69b4b1f4b745867abe4 (patch) | |
tree | e9cf29c394334c02d908058c2c5e159715d3e3c3 /netlib | |
parent | 5b9f07c81c0dcc8c7b3d7afdeae8f6229ebf8622 (diff) | |
download | mitmproxy-09edbd9492e59c0c8dcae69b4b1f4b745867abe4.tar.gz mitmproxy-09edbd9492e59c0c8dcae69b4b1f4b745867abe4.tar.bz2 mitmproxy-09edbd9492e59c0c8dcae69b4b1f4b745867abe4.zip |
Improve debugging of thread and other leaks
- Add basethread.BaseThread that all threads outside of test suites should use
- Add a signal handler to mitmproxy, mitmdump and mitmweb that dumps resource
information to screen when SIGUSR1 is received.
- Improve thread naming throughout to make thread dumps understandable
Diffstat (limited to 'netlib')
-rw-r--r-- | netlib/basethread.py | 14 | ||||
-rw-r--r-- | netlib/debug.py | 71 | ||||
-rw-r--r-- | netlib/tcp.py | 18 |
3 files changed, 86 insertions, 17 deletions
diff --git a/netlib/basethread.py b/netlib/basethread.py new file mode 100644 index 00000000..7963eb7e --- /dev/null +++ b/netlib/basethread.py @@ -0,0 +1,14 @@ +import time +import threading + + +class BaseThread(threading.Thread): + def __init__(self, name, *args, **kwargs): + super(BaseThread, self).__init__(name=name, *args, **kwargs) + self._thread_started = time.time() + + def _threadinfo(self): + return "%s - age: %is" % ( + self.name, + int(time.time() - self._thread_started) + ) diff --git a/netlib/debug.py b/netlib/debug.py index bf446eb0..b48cb122 100644 --- a/netlib/debug.py +++ b/netlib/debug.py @@ -1,29 +1,76 @@ +from __future__ import (absolute_import, print_function, division) + +import sys +import threading +import signal import platform + +import psutil + from netlib import version -""" - Some utilities to help with debugging. -""" def sysinfo(): data = [ - "Mitmproxy verison: %s"%version.VERSION, - "Python version: %s"%platform.python_version(), - "Platform: %s"%platform.platform(), + "Mitmproxy verison: %s" % version.VERSION, + "Python version: %s" % platform.python_version(), + "Platform: %s" % platform.platform(), ] d = platform.linux_distribution() - t = "Linux distro: %s %s %s"%d - if d[0]: # pragma: no-cover + t = "Linux distro: %s %s %s" % d + if d[0]: # pragma: no-cover data.append(t) d = platform.mac_ver() - t = "Mac version: %s %s %s"%d - if d[0]: # pragma: no-cover + t = "Mac version: %s %s %s" % d + if d[0]: # pragma: no-cover data.append(t) d = platform.win32_ver() - t = "Windows version: %s %s %s %s"%d - if d[0]: # pragma: no-cover + t = "Windows version: %s %s %s %s" % d + if d[0]: # pragma: no-cover data.append(t) return "\n".join(data) + + +def dump_info(sig, frm, file=sys.stdout): # pragma: no cover + p = psutil.Process() + + print("****************************************************", file=file) + print("Summary", file=file) + print("=======", file=file) + print("num threads: ", p.num_threads(), file=file) + print("num fds: ", p.num_fds(), file=file) + print("memory: ", p.memory_info(), file=file) + + print(file=file) + print("Threads", file=file) + print("=======", file=file) + bthreads = [] + for i in threading.enumerate(): + if hasattr(i, "_threadinfo"): + bthreads.append(i) + else: + print(i.name, file=file) + bthreads.sort(key=lambda x: x._thread_started) + for i in bthreads: + print(i._threadinfo(), file=file) + + print(file=file) + print("Files", file=file) + print("=====", file=file) + for i in p.open_files(): + print(i, file=file) + + print(file=file) + print("Connections", file=file) + print("===========", file=file) + for i in p.connections(): + print(i, file=file) + + print("****************************************************", file=file) + + +def register_info_dumper(): # pragma: no cover + signal.signal(signal.SIGUSR1, dump_info) diff --git a/netlib/tcp.py b/netlib/tcp.py index 0eec326b..acd67cad 100644 --- a/netlib/tcp.py +++ b/netlib/tcp.py @@ -17,7 +17,11 @@ import six import OpenSSL from OpenSSL import SSL -from netlib import certutils, version_check, basetypes, exceptions +from netlib import certutils +from netlib import version_check +from netlib import basetypes +from netlib import exceptions +from netlib import basethread # This is a rather hackish way to make sure that # the latest version of pyOpenSSL is actually installed. @@ -900,12 +904,16 @@ class TCPServer(object): raise if self.socket in r: connection, client_address = self.socket.accept() - t = threading.Thread( + t = basethread.BaseThread( + "TCPConnectionHandler (%s: %s:%s -> %s:%s)" % ( + self.__class__.__name__, + client_address[0], + client_address[1], + self.address.host, + self.address.port + ), target=self.connection_thread, args=(connection, client_address), - name="ConnectionThread (%s:%s -> %s:%s)" % - (client_address[0], client_address[1], - self.address.host, self.address.port) ) t.setDaemon(1) try: |