1import asyncio 2import gc 3import linecache 4import os 5import platform 6import signal 7import sys 8import threading 9import traceback 10from contextlib import redirect_stdout 11 12from OpenSSL import SSL 13from mitmproxy import version 14from mitmproxy.utils import asyncio_utils 15 16 17def dump_system_info(): 18 mitmproxy_version = version.get_dev_version() 19 20 data = [ 21 f"Mitmproxy: {mitmproxy_version}", 22 f"Python: {platform.python_version()}", 23 "OpenSSL: {}".format(SSL.SSLeay_version(SSL.SSLEAY_VERSION).decode()), 24 f"Platform: {platform.platform()}", 25 ] 26 return "\n".join(data) 27 28 29def dump_info(signal=None, frame=None, file=sys.stdout, testing=False): # pragma: no cover 30 with redirect_stdout(file): 31 print("****************************************************") 32 print("Summary") 33 print("=======") 34 35 try: 36 import psutil 37 except: 38 print("(psutil not installed, skipping some debug info)") 39 else: 40 p = psutil.Process() 41 print("num threads: ", p.num_threads()) 42 if hasattr(p, "num_fds"): 43 print("num fds: ", p.num_fds()) 44 print("memory: ", p.memory_info()) 45 46 print() 47 print("Files") 48 print("=====") 49 for i in p.open_files(): 50 print(i) 51 52 print() 53 print("Connections") 54 print("===========") 55 for i in p.connections(): 56 print(i) 57 58 print() 59 print("Threads") 60 print("=======") 61 bthreads = [] 62 for i in threading.enumerate(): 63 if hasattr(i, "_threadinfo"): 64 bthreads.append(i) 65 else: 66 print(i.name) 67 bthreads.sort(key=lambda x: x._thread_started) 68 for i in bthreads: 69 print(i._threadinfo()) 70 71 print() 72 print("Memory") 73 print("=======") 74 gc.collect() 75 d = {} 76 for i in gc.get_objects(): 77 t = str(type(i)) 78 if "mitmproxy" in t: 79 d[t] = d.setdefault(t, 0) + 1 80 itms = list(d.items()) 81 itms.sort(key=lambda x: x[1]) 82 for i in itms[-20:]: 83 print(i[1], i[0]) 84 85 try: 86 asyncio.get_running_loop() 87 except RuntimeError: 88 pass 89 else: 90 print() 91 print("Tasks") 92 print("=======") 93 for task in asyncio.all_tasks(): 94 f = task.get_stack(limit=1)[0] 95 line = linecache.getline(f.f_code.co_filename, f.f_lineno, f.f_globals).strip() 96 line = f"{line} # at {os.path.basename(f.f_code.co_filename)}:{f.f_lineno}" 97 print(f"{asyncio_utils.task_repr(task)}\n" 98 f" {line}") 99 100 print("****************************************************") 101 102 if not testing: 103 sys.exit(1) 104 105 106def dump_stacks(signal=None, frame=None, file=sys.stdout, testing=False): 107 id2name = {th.ident: th.name for th in threading.enumerate()} 108 code = [] 109 for threadId, stack in sys._current_frames().items(): 110 code.append( 111 "\n# Thread: %s(%d)" % ( 112 id2name.get(threadId, ""), threadId 113 ) 114 ) 115 for filename, lineno, name, line in traceback.extract_stack(stack): 116 code.append('File: "%s", line %d, in %s' % (filename, lineno, name)) 117 if line: 118 code.append(" %s" % (line.strip())) 119 print("\n".join(code), file=file) 120 if not testing: # pragma: no cover 121 sys.exit(1) 122 123 124def register_info_dumpers(): 125 if os.name != "nt": # pragma: windows no cover 126 signal.signal(signal.SIGUSR1, dump_info) 127 signal.signal(signal.SIGUSR2, dump_stacks) 128