microsoft / debugpy

An implementation of the Debug Adapter Protocol for Python
https://pypi.org/project/debugpy/
Other
1.84k stars 136 forks source link

Provide a way to notify users of where a RecursionError happens #814

Open zillionare opened 2 years ago

zillionare commented 2 years ago

VS Code version

1.60.2

Extension version

python: v2021.10.1365161279

OS type

Linux

OS version

ubuntu 20.04

Python distribution

Anaconda

Python version

3.9.7 64-bit

Language server

Pylance

Expected behaviour

No exception

Actual behaviour

============================= test session starts ==============================

platform linux -- Python 3.9.7, pytest-6.1.2, py-1.11.0, pluggy-0.13.1
rootdir: /apps/omega
plugins: cov-2.10.1
collected 1 item

tests/fetcher/test_abstract_quotes_fetcher.py 提示:当前环境 pandas 版本高于 0.25,get_price 与 get_fundamentals_continuously 接口 panel 参数将固定为 False
注意:0.25 以上版本 pandas 不支持 panel,如使用该数据结构和相关函数请注意修改
auth success
Frame skipped from debugging during step-in.
Note: may have been skipped because of "justMyCode" option (default == true). Try setting "justMyCode": false in the debug configuration (e.g., launch.json).
Traceback (most recent call last):
  File "_pydevd_bundle/pydevd_cython.pyx", line 1664, in _pydevd_bundle.pydevd_cython.ThreadTracer.__call__
RecursionError: maximum recursion depth exceeded
Fatal Python error: _Py_CheckRecursiveCall: Cannot recover from stack overflow.
Python runtime state: initialized

Thread 0x00007ff70b524700 (most recent call first):
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 316 in wait
  File "/root/miniconda3/envs/omega/lib/python3.9/queue.py", line 180 in get
  File "/root/miniconda3/envs/omega/lib/python3.9/site-packages/watchdog/observers/api.py", line 364 in dispatch_events
  File "/root/miniconda3/envs/omega/lib/python3.9/site-packages/watchdog/observers/api.py", line 199 in run
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 973 in _bootstrap_inner
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 930 in _bootstrap
  File "/root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydev_bundle/pydev_monkey.py", line 1054 in __call__

Thread 0x00007ff70c526700 (most recent call first):
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 312 in wait
  File "/root/miniconda3/envs/omega/lib/python3.9/site-packages/watchdog/utils/delayed_queue.py", line 54 in get
  File "/root/miniconda3/envs/omega/lib/python3.9/site-packages/watchdog/observers/inotify_buffer.py", line 43 in read_event
  File "/root/miniconda3/envs/omega/lib/python3.9/site-packages/watchdog/observers/inotify.py", line 129 in queue_events
  File "/root/miniconda3/envs/omega/lib/python3.9/site-packages/watchdog/observers/api.py", line 148 in run
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 973 in _bootstrap_inner
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 930 in _bootstrap
  File "/root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydev_bundle/pydev_monkey.py", line 1054 in __call__

Thread 0x00007ff70cd27700 (most recent call first):
  File "/root/miniconda3/envs/omega/lib/python3.9/site-packages/watchdog/observers/inotify_c.py", line 285 in read_events
  File "/root/miniconda3/envs/omega/lib/python3.9/site-packages/watchdog/observers/inotify_buffer.py", line 88 in run
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 973 in _bootstrap_inner
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 930 in _bootstrap
  File "/root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydev_bundle/pydev_monkey.py", line 1054 in __call__

Thread 0x00007ff73affd700 (most recent call first):
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 316 in wait
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 574 in wait
  File "/root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/_vendored/pydevd/pydevd.py", line 246 in _on_run
  File "/root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_daemon_thread.py", line 46 in run
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 973 in _bootstrap_inner
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 930 in _bootstrap

Thread 0x00007ff73b7fe700 (most recent call first):
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 316 in wait
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 574 in wait
  File "/root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/_vendored/pydevd/pydevd.py", line 200 in _on_run
  File "/root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_daemon_thread.py", line 46 in run
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 973 in _bootstrap_inner
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 930 in _bootstrap

Thread 0x00007ff73bfff700 (most recent call first):
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 312 in wait
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 574 in wait
  File "/root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_timeout.py", line 43 in _on_run
  File "/root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_daemon_thread.py", line 46 in run
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 973 in _bootstrap_inner
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 930 in _bootstrap

Thread 0x00007ff74093e700 (most recent call first):
  File "/root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py", line 219 in _read_line
  File "/root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py", line 237 in _on_run
  File "/root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_daemon_thread.py", line 46 in run
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 973 in _bootstrap_inner
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 930 in _bootstrap

Thread 0x00007ff74113f700 (most recent call first):
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 316 in wait
  File "/root/miniconda3/envs/omega/lib/python3.9/queue.py", line 180 in get
  File "/root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py", line 382 in _on_run
  File "/root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_daemon_thread.py", line 46 in run
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 973 in _bootstrap_inner
  File "/root/miniconda3/envs/omega/lib/python3.9/threading.py", line 930 in _bootstrap

Current thread 0x00007ff742b92180 (most recent call first):
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/events.py", line 58 in __repr__
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 139 in repr_instance
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 62 in repr1
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 52 in repr
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 40 in <genexpr>
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 40 in _format_args_and_kwargs
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 56 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 47 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 23 in _format_callback_source
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 32 in format_cb
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 37 in _format_callbacks
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 76 in _future_repr_info
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 139 in repr_instance
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 62 in repr1
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 52 in repr
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 38 in <genexpr>
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 38 in _format_args_and_kwargs
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 56 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 23 in _format_callback_source
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/events.py", line 51 in _repr_info
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/events.py", line 61 in __repr__
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 139 in repr_instance
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 62 in repr1
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 52 in repr
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 40 in <genexpr>
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 40 in _format_args_and_kwargs
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 56 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 47 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 23 in _format_callback_source
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 32 in format_cb
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 37 in _format_callbacks
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 76 in _future_repr_info
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 139 in repr_instance
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 62 in repr1
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 52 in repr
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 38 in <genexpr>
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 38 in _format_args_and_kwargs
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 56 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 23 in _format_callback_source
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/events.py", line 51 in _repr_info
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/events.py", line 61 in __repr__
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 139 in repr_instance
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 62 in repr1
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 52 in repr
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 40 in <genexpr>
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 40 in _format_args_and_kwargs
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 56 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 47 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 23 in _format_callback_source
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 32 in format_cb
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 37 in _format_callbacks
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 76 in _future_repr_info
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 139 in repr_instance
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 62 in repr1
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 52 in repr
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 38 in <genexpr>
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 38 in _format_args_and_kwargs
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 56 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 23 in _format_callback_source
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/events.py", line 51 in _repr_info
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/events.py", line 61 in __repr__
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 139 in repr_instance
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 62 in repr1
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 52 in repr
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 40 in <genexpr>
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 40 in _format_args_and_kwargs
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 56 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 47 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 23 in _format_callback_source
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 32 in format_cb
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 37 in _format_callbacks
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 76 in _future_repr_info
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 139 in repr_instance
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 62 in repr1
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 52 in repr
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 38 in <genexpr>
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 38 in _format_args_and_kwargs
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 56 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 23 in _format_callback_source
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/events.py", line 51 in _repr_info
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/events.py", line 61 in __repr__
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 139 in repr_instance
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 62 in repr1
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 52 in repr
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 40 in <genexpr>
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 40 in _format_args_and_kwargs
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 56 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 47 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 23 in _format_callback_source
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 32 in format_cb
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 37 in _format_callbacks
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/base_futures.py", line 76 in _future_repr_info
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 139 in repr_instance
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 62 in repr1
  File "/root/miniconda3/envs/omega/lib/python3.9/reprlib.py", line 52 in repr
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 38 in <genexpr>
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 38 in _format_args_and_kwargs
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 56 in _format_callback
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/format_helpers.py", line 23 in _format_callback_source
  File "/root/miniconda3/envs/omega/lib/python3.9/asyncio/events.py", line 51 in _repr_info
  ...

Steps to reproduce

Not 100% producible. Occurs more on virtual machines runs on one ESXi servers, but not always.

Logs

No response

Code of Conduct

zillionare commented 2 years ago

we have reproduced this problem, it caused by aioredis and ms-python, unitest together.

reproduce steps:

  1. install aioredis 1.3.1 (2.0.1 also has same problem)
  2. set breakpoint on line 16 of cache.py
  3. run unittest test case.
  4. when program paused on line 16: await redis.set("test", int(time.time()), let program continue

Now you'll get above exception.

If you run unittest without breakpoints, no exceptions.

Hope this helps.

redis_test.zip .

zillionare commented 2 years ago

we have created a issue for tracking this: https://github.com/zillionare/omega/issues/46 the branch can reproduce this pr is: https://github.com/zillionare/omega/tree/zillionare/issue46

To reproduce:

  1. git clone the code
  2. run pip install poetry, poetry install -E test
  3. debug unittest tests/jobs/test_syncjobs.py::TestSyncJobs::test_load_sync_params
int19h commented 2 years ago

If you set the environment variable PYDEVD_USE_FRAME_EVAL to NO, does it still repro?

zillionare commented 2 years ago

yes, it is still reproducible. If you by any chance want to reproduce this issue by yourself, make sure run several times, if it's not reproduced at the very begining.

fabioz commented 2 years ago

From the traceback it seems that there is some recursion when trying to obtain the repr or get some attribute of some object which is using the asyncio structure.

It's expected from the debugger that it asks for the string representation/gets attributes of many objects (and that objects don't stack-overflow when doing that).

The debugging probably doesn't need anything in the debugger itself... I suggest you change the repr_instance method inside of reprlib and implement some basic recursion check so that it throws an error if it it starts to recurse (say, more than 5 recursive calls) and then invoke the debugger in such a situation.

I'll leave it open for your feedback, but from the issue report (even though the debugger makes it happen), it doesn't really seem like the bug lies in the debugger, but in the code you're debugging (the whole recursion chain doesn't include anything from the debugger -- it probably works sometimes because stack-overflows don't always crash Python, only sometimes and you're seeing these times in the printed traceback, but my guess is that you're almost always getting the stack overflows and that you can discover it by doing some basic recursion check inside of repr_instance).

fabioz commented 2 years ago

I was thinking that maybe this could be turned into a feature in the debugger so that whenever a given recursion level is reached in Python the debugger could notify the user about it.

The unfortunate part is that I know of no way to just get a count for the current recursion level, so, I think the debugger would need to walk through the frame.f_back until the root is reached whenever function is entered (and that could make debugging considerably slower), but as a way to at least notify the user where this happens in cases like this it may be worth having this option even if it's slow...

Ideally we could just hook into Python to call a function when the recursion limit is reached, but I think there's no API for that.

fabioz commented 2 years ago

Mental note: we could use ctypes to get the thread state recursion_remaining to know if the recursion limit is being reached in CPython.