stacks.py 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. # Copyright (c) Microsoft Corporation. All rights reserved.
  2. # Licensed under the MIT License. See LICENSE in the project root
  3. # for license information.
  4. """Provides facilities to dump all stacks of all threads in the process.
  5. """
  6. import os
  7. import sys
  8. import time
  9. import threading
  10. import traceback
  11. from debugpy.common import log
  12. def dump():
  13. """Dump stacks of all threads in this process, except for the current thread."""
  14. tid = threading.current_thread().ident
  15. pid = os.getpid()
  16. log.info("Dumping stacks for process {0}...", pid)
  17. for t_ident, frame in sys._current_frames().items():
  18. if t_ident == tid:
  19. continue
  20. for t in threading.enumerate():
  21. if t.ident == tid:
  22. t_name = t.name
  23. t_daemon = t.daemon
  24. break
  25. else:
  26. t_name = t_daemon = "<unknown>"
  27. stack = "".join(traceback.format_stack(frame))
  28. log.info(
  29. "Stack of thread {0} (tid={1}, pid={2}, daemon={3}):\n\n{4}",
  30. t_name,
  31. t_ident,
  32. pid,
  33. t_daemon,
  34. stack,
  35. )
  36. log.info("Finished dumping stacks for process {0}.", pid)
  37. def dump_after(secs):
  38. """Invokes dump() on a background thread after waiting for the specified time."""
  39. def dumper():
  40. time.sleep(secs)
  41. try:
  42. dump()
  43. except:
  44. log.swallow_exception()
  45. thread = threading.Thread(target=dumper)
  46. thread.daemon = True
  47. thread.start()