mirror of
https://github.com/9001/copyparty.git
synced 2025-08-18 09:22:31 -06:00
add threadwatcher
This commit is contained in:
parent
6da63fbd79
commit
48a2e1a353
|
@ -23,7 +23,7 @@ from textwrap import dedent
|
||||||
from .__init__ import E, WINDOWS, VT100, PY2
|
from .__init__ import E, WINDOWS, VT100, PY2
|
||||||
from .__version__ import S_VERSION, S_BUILD_DT, CODENAME
|
from .__version__ import S_VERSION, S_BUILD_DT, CODENAME
|
||||||
from .svchub import SvcHub
|
from .svchub import SvcHub
|
||||||
from .util import py_desc, align_tab, IMPLICATIONS
|
from .util import py_desc, align_tab, IMPLICATIONS, alltrace
|
||||||
|
|
||||||
HAVE_SSL = True
|
HAVE_SSL = True
|
||||||
try:
|
try:
|
||||||
|
@ -182,6 +182,16 @@ def sighandler(sig=None, frame=None):
|
||||||
print("\n".join(msg))
|
print("\n".join(msg))
|
||||||
|
|
||||||
|
|
||||||
|
def stackmon(fp, ival):
|
||||||
|
ctr = 0
|
||||||
|
while True:
|
||||||
|
ctr += 1
|
||||||
|
time.sleep(ival)
|
||||||
|
st = "{}, {}\n{}".format(ctr, time.time(), alltrace())
|
||||||
|
with open(fp, "wb") as f:
|
||||||
|
f.write(st.encode("utf-8", "replace"))
|
||||||
|
|
||||||
|
|
||||||
def run_argparse(argv, formatter):
|
def run_argparse(argv, formatter):
|
||||||
ap = argparse.ArgumentParser(
|
ap = argparse.ArgumentParser(
|
||||||
formatter_class=formatter,
|
formatter_class=formatter,
|
||||||
|
@ -320,6 +330,7 @@ def run_argparse(argv, formatter):
|
||||||
ap2.add_argument("--no-sendfile", action="store_true", help="disable sendfile")
|
ap2.add_argument("--no-sendfile", action="store_true", help="disable sendfile")
|
||||||
ap2.add_argument("--no-scandir", action="store_true", help="disable scandir")
|
ap2.add_argument("--no-scandir", action="store_true", help="disable scandir")
|
||||||
ap2.add_argument("--no-fastboot", action="store_true", help="wait for up2k indexing")
|
ap2.add_argument("--no-fastboot", action="store_true", help="wait for up2k indexing")
|
||||||
|
ap2.add_argument("--stackmon", metavar="P,S", help="write stacktrace to Path every S second")
|
||||||
|
|
||||||
return ap.parse_args(args=argv[1:])
|
return ap.parse_args(args=argv[1:])
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
@ -359,6 +370,16 @@ def main(argv=None):
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
al = run_argparse(argv, Dodge11874)
|
al = run_argparse(argv, Dodge11874)
|
||||||
|
|
||||||
|
if al.stackmon:
|
||||||
|
fp, f = al.stackmon.rsplit(",", 1)
|
||||||
|
f = int(f)
|
||||||
|
t = threading.Thread(
|
||||||
|
target=stackmon,
|
||||||
|
args=(fp, f),
|
||||||
|
)
|
||||||
|
t.daemon = True
|
||||||
|
t.start()
|
||||||
|
|
||||||
# propagate implications
|
# propagate implications
|
||||||
for k1, k2 in IMPLICATIONS:
|
for k1, k2 in IMPLICATIONS:
|
||||||
if getattr(al, k1):
|
if getattr(al, k1):
|
||||||
|
|
|
@ -1434,33 +1434,8 @@ class HttpCli(object):
|
||||||
if self.args.no_stack:
|
if self.args.no_stack:
|
||||||
raise Pebkac(403, "disabled by argv")
|
raise Pebkac(403, "disabled by argv")
|
||||||
|
|
||||||
threads = {}
|
ret = "<pre>{}\n{}".format(time.time(), alltrace())
|
||||||
names = dict([(t.ident, t.name) for t in threading.enumerate()])
|
self.reply(ret.encode("utf-8"))
|
||||||
for tid, stack in sys._current_frames().items():
|
|
||||||
name = "{} ({:x})".format(names.get(tid), tid)
|
|
||||||
threads[name] = stack
|
|
||||||
|
|
||||||
rret = []
|
|
||||||
bret = []
|
|
||||||
for name, stack in sorted(threads.items()):
|
|
||||||
ret = ["\n\n# {}".format(name)]
|
|
||||||
pad = None
|
|
||||||
for fn, lno, name, line in traceback.extract_stack(stack):
|
|
||||||
fn = os.sep.join(fn.split(os.sep)[-3:])
|
|
||||||
ret.append('File: "{}", line {}, in {}'.format(fn, lno, name))
|
|
||||||
if line:
|
|
||||||
ret.append(" " + str(line.strip()))
|
|
||||||
if "self.not_empty.wait()" in line:
|
|
||||||
pad = " " * 4
|
|
||||||
|
|
||||||
if pad:
|
|
||||||
bret += [ret[0]] + [pad + x for x in ret[1:]]
|
|
||||||
else:
|
|
||||||
rret += ret
|
|
||||||
|
|
||||||
ret = rret + bret
|
|
||||||
ret = ("<pre>" + "\n".join(ret)).encode("utf-8")
|
|
||||||
self.reply(ret)
|
|
||||||
|
|
||||||
def tx_tree(self):
|
def tx_tree(self):
|
||||||
top = self.uparam["tree"] or ""
|
top = self.uparam["tree"] or ""
|
||||||
|
|
|
@ -254,6 +254,34 @@ def trace(*args, **kwargs):
|
||||||
nuprint(msg)
|
nuprint(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def alltrace():
|
||||||
|
threads = {}
|
||||||
|
names = dict([(t.ident, t.name) for t in threading.enumerate()])
|
||||||
|
for tid, stack in sys._current_frames().items():
|
||||||
|
name = "{} ({:x})".format(names.get(tid), tid)
|
||||||
|
threads[name] = stack
|
||||||
|
|
||||||
|
rret = []
|
||||||
|
bret = []
|
||||||
|
for name, stack in sorted(threads.items()):
|
||||||
|
ret = ["\n\n# {}".format(name)]
|
||||||
|
pad = None
|
||||||
|
for fn, lno, name, line in traceback.extract_stack(stack):
|
||||||
|
fn = os.sep.join(fn.split(os.sep)[-3:])
|
||||||
|
ret.append('File: "{}", line {}, in {}'.format(fn, lno, name))
|
||||||
|
if line:
|
||||||
|
ret.append(" " + str(line.strip()))
|
||||||
|
if "self.not_empty.wait()" in line:
|
||||||
|
pad = " " * 4
|
||||||
|
|
||||||
|
if pad:
|
||||||
|
bret += [ret[0]] + [pad + x for x in ret[1:]]
|
||||||
|
else:
|
||||||
|
rret += ret
|
||||||
|
|
||||||
|
return "\n".join(rret + bret)
|
||||||
|
|
||||||
|
|
||||||
def min_ex():
|
def min_ex():
|
||||||
et, ev, tb = sys.exc_info()
|
et, ev, tb = sys.exc_info()
|
||||||
tb = traceback.extract_tb(tb, 2)
|
tb = traceback.extract_tb(tb, 2)
|
||||||
|
|
Loading…
Reference in a new issue