puremourning / vimspector

vimspector - A multi-language debugging system for Vim
http://puremourning.github.io/vimspector-web
Apache License 2.0
4.08k stars 171 forks source link

[Feature Request] Multiple concurrent sessions (to debug multiprocessing python programs) #141

Closed moetayuko closed 1 year ago

moetayuko commented 4 years ago

Describe the bug Can't debug multiprocessing python programs

To Reproduce MWE

import time
import multiprocessing as mp

def f():
    while True:
        print("f")
        time.sleep(0.1)

print("main")
p = mp.Process(target=f)
p.start()
p.join()

List of steps to reproduce

  1. Set a breakpoint in f()
  2. Start debugging

Vimspector config file:

{
  "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json#",
  "configurations": {
    "Current file: Launch": {
      "adapter": "debugpy",
      "configuration": {
        "name": "Current file: Launch",
        "request": "launch",
        "console": "externalTerminal",
        "program": "${file}"
      }
    }
  }
}

Expected behavior Stop at the breakpoint.

Actual behaviour Stop at p.join() and stuck there.

Please include:

http://fars.ee/l00b

Unhandled event: debugpyAttach

Environemnt

NOTE: NeoVim is supported only on a best-effort basis. Please check the README for limitations of neovim. Don't be offended if I ask you to reproduce issues in Vim.

NOTE: Windows is not supported. There is a branch with windows support, which you can contribute to, rather than opening an issue.

VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Mar  1 2020 17:21:03)
Included patches: 1-343
Compiled by Arch Linux
Huge version without GUI.  Features included (+) or not (-):
+acl               -farsi             -mouse_sysmouse    -tag_old_static
+arabic            +file_in_path      +mouse_urxvt       -tag_any_white
+autocmd           +find_in_path      +mouse_xterm       +tcl/dyn
+autochdir         +float             +multi_byte        +termguicolors
-autoservername    +folding           +multi_lang        +terminal
-balloon_eval      -footer            -mzscheme          +terminfo
+balloon_eval_term +fork()            +netbeans_intg     +termresponse
-browse            +gettext           +num64             +textobjects
++builtin_terms    -hangul_input      +packages          +textprop
+byte_offset       +iconv             +path_extra        +timers
+channel           +insert_expand     +perl/dyn          +title
+cindent           +job               +persistent_undo   -toolbar
-clientserver      +jumplist          +popupwin          +user_commands
-clipboard         +keymap            +postscript        +vartabs
+cmdline_compl     +lambda            +printer           +vertsplit
+cmdline_hist      +langmap           +profile           +virtualedit
+cmdline_info      +libcall           +python/dyn        +visual
+comments          +linebreak         +python3/dyn       +visualextra
+conceal           +lispindent        +quickfix          +viminfo
+cryptv            +listcmds          +reltime           +vreplace
+cscope            +localmap          +rightleft         +wildignore
+cursorbind        +lua/dyn           +ruby/dyn          +wildmenu
+cursorshape       +menu              +scrollbind        +windows
+dialog_con        +mksession         +signs             +writebackup
+diff              +modify_fname      +smartindent       -X11
+digraphs          +mouse             -sound             -xfontset
-dnd               -mouseshape        +spell             -xim
-ebcdic            +mouse_dec         +startuptime       -xpm
+emacs_tags        +mouse_gpm         +statusline        -xsmp
+eval              -mouse_jsbterm     -sun_workshop      -xterm_clipboard
+ex_extra          +mouse_netterm     +syntax            -xterm_save
+extra_search      +mouse_sgr         +tag_binary        
   system vimrc file: "/etc/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
  fall-back for $VIM: "/usr/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H     -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1       
Linking: gcc   -L. -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -fstack-protector-strong -rdynamic -Wl,-export-dynamic -Wl,-E -Wl,-rpath,/usr/lib/perl5/5.30/core_perl/CORE  -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -L/usr/local/lib -Wl,--as-needed -o vim        -lm -ltinfo -lelf -lnsl    -lacl -lattr -lgpm -ldl   -Wl,-E -Wl,-rpath,/usr/lib/perl5/5.30/core_perl/CORE -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -fstack-protector-strong -L/usr/local/lib  -L/usr/lib/perl5/5.30/core_perl/CORE -lperl -lpthread -ldl -lm -lcrypt -lutil -lc   -L/usr/lib -ltclstub8.6 -ldl -lz -lpthread -lm     
/usr/sbin/vim
nothing
nothing

Additional context This works in vscode

puremourning commented 4 years ago

Thanks for the detailed report. If i remember correctly there is some flag you can pass to the debug adapter to tell it to debug into child processes.

Googling debugpy child processes yields this: https://github.com/microsoft/debugpy/blob/master/doc/Subprocess%20debugging.md not sure if that's useful or not.

The unhandled event <clearly custom event name here> is also suspicious. If the debug adapter is using non standard events, then Vimspector's not going to be able to support it.

(i refuse to implement anything outside of the protocol as i do not have the bandwidth to do this).

puremourning commented 4 years ago

@int19h - any advise on this one ? Is there anything special that's required for debugpy to debug into child processes created by multiprocessing.Process() ?

puremourning commented 4 years ago

There's certainly some shenanigans in the log here:

2020-03-27 19:56:35,079 - DEBUG - Message received: {'seq': 14, 'type': 'event', 'event': 'debugpyAttach', 'body': {'python': '/usr/sbin/python3', 'name': 'Subprocess 12078', 'request': 'attach', 'console': 'externalTerminal', 'program': '/tmp/test.py', 'host': '127.0.0.1', 'port': 36197, 'subProcessId': 12078}}
2020-03-27 19:56:35,079 - WARNING - User Msg: Unhandled event: debugpyAttach
2020-03-27 19:56:35,079 - DEBUG - Message received: {'seq': 15, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 0, 'name': 'multiprocessing.popen_fork', 'path': '/usr/lib/python3.8/multiprocessing/popen_fork.py', 'package': 'multiprocessing'}}}
2020-03-27 19:56:35,080 - DEBUG - Message received: {'seq': 16, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 1, 'name': 'multiprocessing.process', 'path': '/usr/lib/python3.8/multiprocessing/process.py', 'package': 'multiprocessing'}}}
2020-03-27 19:56:35,080 - DEBUG - Message received: {'seq': 17, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 2, 'name': '__main__', 'path': '/tmp/test.py'}}}
2020-03-27 19:56:35,080 - DEBUG - Message received: {'seq': 18, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 3, 'name': 'runpy', 'path': '/usr/lib/python3.8/runpy.py'}}}
2020-03-27 19:56:35,080 - DEBUG - Message received: {'seq': 19, 'type': 'response', 'request_seq': 8, 'success': True, 'command': 'scopes', 'body': {'scopes': [{'name': 'Locals', 'variablesReference': 2, 'expensive': False, 'source': {}}]}}
2020-03-27 19:56:35,080 - DEBUG - Sending Message: {"command": "variables", "arguments": {"variablesReference": 2}, "seq": 9, "type": "request"}
2020-03-27 19:56:35,080 - DEBUG - Calling: vimspector#internal#job#Send(g:vimspector_internal_arg_0)
2020-03-27 19:56:35,107 - DEBUG - Message received: {'seq': 20, 'type': 'response', 'request_seq': 9, 'success': False, 'command': 'variables', 'message': 'Unable to find thread to evaluate variable reference.'}
2020-03-27 19:56:35,108 - ERROR - Request failed: Unable to find thread to evaluate variable reference.
2020-03-27 19:56:35,332 - INFO - Server stderr: E+00004.427: /handling #9 request "variables" from IDE[1]/
             Handler 'IDE.request' (file '/home/dianlujitao/.vim/plugged/vimspector/gadgets/linux/debugpy/build/lib/debugpy/adapter/../../debugpy/adapter/components.py', line 127)
             couldn't handle #9 request "variables" from IDE[1]:
             Unable to find thread to evaluate variable reference.
moetayuko commented 4 years ago

The unhandled event <clearly custom event name here> is also suspicious. If the debug adapter is using non standard events, then Vimspector's not going to be able to support it.

vscode's python plugin handles it in a handleCustomEvent function so...it's probably not part of the standard DAP

puremourning commented 4 years ago

Yes, it would seem that there is some collusion between the debug adapter and its VSCode extension to handle this multi-process debugging. In VSCode do you get like multiple debug sessions (one attached to the parent and one attached to the spawned child process ? )

moetayuko commented 4 years ago

In VSCode do you get like multiple debug sessions (one attached to the parent and one attached to the spawned child process ? )

Yes, each process has its own session. To make it clear I extended the example to create two sub-processes:

import time
import multiprocessing as mp

def f1():
    while True:
        print("f1")
        time.sleep(0.1)

def f2():
    while True:
        print("f2")
        time.sleep(0.1)

print("main")
p1 = mp.Process(target=f1)
p1.start()
p2 = mp.Process(target=f2)
p2.start()

p1.join()
p2.join()

After executing p1.start(), a new session was created, the parent session was paused and the debugging window automatically attached to the new session:

image

I can re-attach to the parent session from "call stack" window like this:

image

and continue to start the next process:

image

"variables" and "watch" windows change when switching between sessions.

Multi-processing support is quite important for python, not only for debugging sub-processes, but also for debugging the main process itself, because the debugger stuck once a new process was created even if no breakpoint was set within sub-processes. I'd really appreciate it if this could be implemented.

puremourning commented 4 years ago

Vimspector doesn't support multiple concurrent debug sessions of any type right now, and this is clearly using custom features unique to the vscode-python extension, so there's not really much hope of this being supported, unless something changes in DAP.

int19h commented 4 years ago

Yep, the way DAP is structured, every process has to be its own separate session. On debugpy side, when subprocess is detected and detoured, we send a custom event that basically contains the body of the "attach" event that is necessary to attach to that subprocess - the client has to handle that accordingly.

We are hoping to submit this sort of "reverse attach request" for standardization in the main protocol eventually. But that will only happen after this custom implementation had some time to prove that it's a solid approach.

When it's not supported, to avoid child processes getting stuck because the client is not there to attach to them, the debug configuration should specify "subProcess": false.

moetayuko commented 4 years ago

I added "subProcess": false as Pavel mentioned, and according to the logging it's actually sent to the debugger:

2020-03-28 10:54:09,766 - DEBUG - Sending Message: {"command": "launch", "arguments": {"python": "/usr/sbin/python3", "name": "Current file: Launch", "request": "launch", "subProcess": false, "console": "externalTerminal", "program": "/tmp/test.py"}, "seq": 1, "type": "request"}

But the debugpyAttach event along with the attach request was still sent to vimspector and stuck at .join()

Anything wrong with my configuration?

int19h commented 4 years ago

Nope, it's correct - the problem is that we regressed "subProcess" :/

I'll track this as https://github.com/microsoft/debugpy/issues/90

puremourning commented 3 years ago

Looks like we would need to also handle the "process" event which I think we currently ignore:

2020-12-01 18:47:04,928 - DEBUG - Message received: {'seq': 9, 'type': 'event', 'event': 'process', 'body': {'name': 'manage.py', 'systemProcessId': 77, 'isLocalProcess': True, 'startMethod': 'attach'}}

https://microsoft.github.io/debug-adapter-protocol/specification#Events_Process

another log from @ross-weir https://gist.github.com/ross-weir/5de8fce2ab53eb34e4a71ae2d4e7eb5b

ross-weir commented 3 years ago

@puremourning Maybe/maybe not useful, full log attaching to a subprocess using the body object as the configuration from a debugpyAttach event. Connecting to the subprocess was successful and debuggable.

2020-12-01 20:36:45,938 - DEBUG - Reading configurations from: None
2020-12-01 20:36:45,939 - DEBUG - Reading configurations from: /Users/user/Development/app/.vimspector.json
2020-12-01 20:36:45,949 - DEBUG - Reading gadget config: /Users/user/.vim/plugged/vimspector/gadgets/macos/.gadgets.json
2020-12-01 20:36:45,951 - DEBUG - Reading gadget config: None
2020-12-01 20:36:47,801 - INFO - Configuration: {"adapter": "multi-session", "variables": {"host": "127.0.0.1", "port": "22961"}, "breakpoints": {"exception": {"raised": "N", "uncaught": "", "userUnhandled": ""}}, "configuration": {"request": "attach", "django": true, "type": "python", "name": "Subprocess 98", "connect": {"host": "127.0.0.1", "port": 22961}, "subProcessId": 98, "pathMappings": [{"localRoot": "/Users/user/Development/app", "remoteRoot": "/opt/app"}]}}
2020-12-01 20:36:47,802 - INFO - Adapter: {"host": "127.0.0.1", "port": "22961"}
2020-12-01 20:36:48,097 - INFO - Starting debug adapter with: {"host": "127.0.0.1", "port": "22961"}
2020-12-01 20:36:48,100 - INFO - Debug Adapter Started
2020-12-01 20:36:48,101 - DEBUG - Sending Message: {"command": "initialize", "arguments": {"adapterID": "adapter", "clientID": "vimspector", "clientName": "vimspector", "linesStartAt1": true, "columnsStartAt1": true, "locale": "en_GB", "pathFormat": "path", "supportsVariableType": true, "supportsVariablePaging": false, "supportsRunInTerminalRequest": true}, "seq": 0, "type": "request"}
2020-12-01 20:36:48,210 - DEBUG - Message received: {'seq': 1, 'type': 'event', 'event': 'output', 'body': {'category': 'telemetry', 'output': 'ptvsd', 'data': {'packageVersion': '1.2.0'}}}
2020-12-01 20:36:48,241 - DEBUG - Message received: {'seq': 2, 'type': 'event', 'event': 'output', 'body': {'category': 'telemetry', 'output': 'debugpy', 'data': {'packageVersion': '1.2.0'}}}
2020-12-01 20:36:48,266 - DEBUG - Message received: {'seq': 3, 'type': 'response', 'request_seq': 0, 'success': True, 'command': 'initialize', 'body': {'supportsCompletionsRequest': True, 'supportsConditionalBreakpoints': True, 'supportsConfigurationDoneRequest': True, 'supportsDebuggerProperties': True, 'supportsDelayedStackTraceLoading': True, 'supportsEvaluateForHovers': True, 'supportsExceptionInfoRequest': True, 'supportsExceptionOptions': True, 'supportsHitConditionalBreakpoints': True, 'supportsLogPoints': True, 'supportsModulesRequest': True, 'supportsSetExpression': True, 'supportsSetVariable': True, 'supportsValueFormattingOptions': True, 'supportsTerminateDebuggee': True, 'supportsGotoTargetsRequest': True, 'exceptionBreakpointFilters': [{'filter': 'raised', 'label': 'Raised Exceptions', 'default': False}, {'filter': 'uncaught', 'label': 'Uncaught Exceptions', 'default': True}]}}
2020-12-01 20:36:48,267 - DEBUG - LAUNCH!
2020-12-01 20:36:48,267 - DEBUG - Sending Message: {"command": "attach", "arguments": {"request": "attach", "django": true, "type": "python", "name": "Subprocess 98", "connect": {"host": "127.0.0.1", "port": 22961}, "subProcessId": 98, "pathMappings": [{"localRoot": "/Users/user/Development/app", "remoteRoot": "/opt/app"}]}, "seq": 1, "type": "request"}
2020-12-01 20:36:48,289 - DEBUG - Message received: {'seq': 4, 'type': 'event', 'event': 'debugpyWaitingForServer', 'body': {'host': '127.0.0.1', 'port': 35331}}
2020-12-01 20:36:48,289 - WARNING - User Msg: Unhandled event: debugpyWaitingForServer
2020-12-01 20:36:48,441 - DEBUG - Message received: {'seq': 5, 'type': 'event', 'event': 'initialized'}
2020-12-01 20:36:48,443 - DEBUG - Sending Message: {"command": "setBreakpoints", "arguments": {"source": {"name": "thing.py", "path": "/Users/user/Development/app/lbs/api_internal/things/viewsets/thing.py"}, "breakpoints": [{"line": 125}]}, "sourceModified": false, "seq": 2, "type": "request"}
2020-12-01 20:36:48,444 - DEBUG - Sending Message: {"command": "setExceptionBreakpoints", "arguments": {"filters": ["uncaught"], "exceptionOptions": []}, "seq": 3, "type": "request"}
2020-12-01 20:36:48,509 - DEBUG - Message received: {'seq': 6, 'type': 'response', 'request_seq': 2, 'success': True, 'command': 'setBreakpoints', 'body': {'breakpoints': [{'verified': True, 'id': 1, 'source': {'name': 'thing.py', 'path': '/Users/user/Development/app/lbs/api_internal/things/viewsets/thing.py'}, 'line': 125}]}}
2020-12-01 20:36:48,510 - DEBUG - Breakpoints at this point: {
  "/Users/user/Development/app/lbs/api_internal/things/viewsets/thing.py": [
    {
      "verified": true,
      "id": 1,
      "source": {
        "name": "thing.py",
        "path": "/Users/user/Development/app/lbs/api_internal/things/viewsets/thing.py"
      },
      "line": 125
    }
  ]
}
2020-12-01 20:36:48,560 - DEBUG - Message received: {'seq': 7, 'type': 'response', 'request_seq': 3, 'success': True, 'command': 'setExceptionBreakpoints'}
2020-12-01 20:36:48,561 - DEBUG - Sending Message: {"command": "configurationDone", "seq": 4, "type": "request"}
2020-12-01 20:36:48,617 - DEBUG - Message received: {'seq': 8, 'type': 'response', 'request_seq': 4, 'success': True, 'command': 'configurationDone'}
2020-12-01 20:36:48,656 - DEBUG - Message received: {'seq': 9, 'type': 'response', 'request_seq': 1, 'success': True, 'command': 'attach'}
2020-12-01 20:36:48,657 - DEBUG - Sending Message: {"command": "threads", "seq": 5, "type": "request"}
2020-12-01 20:36:48,657 - DEBUG - Message received: {'seq': 10, 'type': 'event', 'event': 'process', 'body': {'name': 'manage.py', 'systemProcessId': 98, 'isLocalProcess': True, 'startMethod': 'attach'}}
2020-12-01 20:36:48,657 - INFO - User Msg: The debugee was started: manage.py
2020-12-01 20:36:48,696 - DEBUG - Message received: {'seq': 11, 'type': 'event', 'event': 'thread', 'body': {'reason': 'started', 'threadId': 1}}
2020-12-01 20:36:48,696 - DEBUG - Message received: {'seq': 12, 'type': 'event', 'event': 'thread', 'body': {'reason': 'started', 'threadId': 2}}
2020-12-01 20:36:48,698 - DEBUG - Message received: {'seq': 13, 'type': 'event', 'event': 'thread', 'body': {'reason': 'started', 'threadId': 3}}
2020-12-01 20:36:48,699 - DEBUG - Message received: {'seq': 14, 'type': 'event', 'event': 'thread', 'body': {'reason': 'started', 'threadId': 4}}
2020-12-01 20:36:48,699 - DEBUG - Message received: {'seq': 15, 'type': 'event', 'event': 'thread', 'body': {'reason': 'started', 'threadId': 5}}
2020-12-01 20:36:48,700 - DEBUG - Message received: {'seq': 16, 'type': 'response', 'request_seq': 5, 'success': True, 'command': 'threads', 'body': {'threads': [{'id': 1, 'name': 'MainThread'}, {'id': 2, 'name': 'django-main-thread'}, {'id': 3, 'name': 'ThreadPoolExecutor-0_0'}, {'id': 4, 'name': 'ThreadPoolExecutor-1_0'}, {'id': 5, 'name': 'ThreadPoolExecutor-1_1'}]}}
2020-12-01 20:36:48,701 - DEBUG - Sending Message: {"command": "threads", "seq": 6, "type": "request"}
2020-12-01 20:36:48,737 - DEBUG - Message received: {'seq': 17, 'type': 'response', 'request_seq': 6, 'success': True, 'command': 'threads', 'body': {'threads': [{'id': 1, 'name': 'MainThread'}, {'id': 2, 'name': 'django-main-thread'}, {'id': 3, 'name': 'ThreadPoolExecutor-0_0'}, {'id': 4, 'name': 'ThreadPoolExecutor-1_0'}, {'id': 5, 'name': 'ThreadPoolExecutor-1_1'}]}}
2020-12-01 20:37:21,090 - DEBUG - Message received: {'seq': 18, 'type': 'event', 'event': 'stopped', 'body': {'reason': 'breakpoint', 'threadId': 3, 'preserveFocusHint': False, 'allThreadsStopped': True}}
2020-12-01 20:37:21,090 - WARNING - User Msg: Paused in thread 3 due to breakpoint
2020-12-01 20:37:21,137 - DEBUG - Sending Message: {"command": "threads", "seq": 7, "type": "request"}
2020-12-01 20:37:21,317 - DEBUG - Message received: {'seq': 19, 'type': 'response', 'request_seq': 7, 'success': True, 'command': 'threads', 'body': {'threads': [{'id': 1, 'name': 'MainThread'}, {'id': 2, 'name': 'django-main-thread'}, {'id': 3, 'name': 'ThreadPoolExecutor-0_0'}, {'id': 4, 'name': 'ThreadPoolExecutor-1_0'}, {'id': 5, 'name': 'ThreadPoolExecutor-1_1'}]}}
2020-12-01 20:37:21,319 - DEBUG - Sending Message: {"command": "stackTrace", "arguments": {"threadId": 3}, "seq": 8, "type": "request"}
2020-12-01 20:37:21,534 - DEBUG - Message received: {'seq': 20, 'type': 'response', 'request_seq': 8, 'success': True, 'command': 'stackTrace', 'body': {'stackFrames': [{'id': 6, 'name': 'get_queryset', 'line': 125, 'column': 1, 'source': {'path': '/Users/user/Development/app/lbs/api_internal/things/viewsets/thing.py', 'sourceReference': 0}}, {'id': 7, 'name': 'do_revision_view', 'line': 55, 'column': 1, 'source': {'path': '/Users/user/Development/app/lbs/core/middleware.py', 'sourceReference': 0}}], 'totalFrames': 2}}
2020-12-01 20:37:21,798 - DEBUG - Sending Message: {"command": "scopes", "arguments": {"frameId": 6}, "seq": 9, "type": "request"}
2020-12-01 20:37:21,801 - DEBUG - Message received: {'seq': 21, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 0, 'name': 'lbs.api_internal.things.viewsets.thing', 'path': '/Users/user/Development/app/lbs/api_internal/things/viewsets/thing.py', 'package': 'lbs.api_internal.things.viewsets'}}}
2020-12-01 20:37:21,999 - DEBUG - Message received: {'seq': 22, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 1, 'name': 'rest_framework.mixins', 'path': '/usr/local/lib/python3.7/site-packages/rest_framework/mixins.py', 'package': 'rest_framework'}}}
2020-12-01 20:37:22,000 - DEBUG - Message received: {'seq': 23, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 2, 'name': 'rest_framework.views', 'path': '/usr/local/lib/python3.7/site-packages/rest_framework/views.py', 'package': 'rest_framework'}}}
2020-12-01 20:37:22,000 - DEBUG - Message received: {'seq': 24, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 3, 'name': 'rest_framework.viewsets', 'path': '/usr/local/lib/python3.7/site-packages/rest_framework/viewsets.py', 'package': 'rest_framework'}}}
2020-12-01 20:37:22,001 - DEBUG - Message received: {'seq': 25, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 4, 'name': 'django.views.decorators.csrf', 'path': '/usr/local/lib/python3.7/site-packages/django/views/decorators/csrf.py', 'package': 'django.views.decorators'}}}
2020-12-01 20:37:22,001 - DEBUG - Message received: {'seq': 26, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 5, 'name': 'django.core.handlers.base', 'path': '/usr/local/lib/python3.7/site-packages/django/core/handlers/base.py', 'package': 'django.core.handlers'}}}
2020-12-01 20:37:22,001 - DEBUG - Message received: {'seq': 27, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 6, 'name': 'django.core.handlers.exception', 'path': '/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py', 'package': 'django.core.handlers'}}}
2020-12-01 20:37:22,003 - DEBUG - Message received: {'seq': 28, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 7, 'name': 'debug_toolbar.middleware', 'path': '/usr/local/lib/python3.7/site-packages/debug_toolbar/middleware.py', 'package': 'debug_toolbar'}}}
2020-12-01 20:37:22,003 - DEBUG - Message received: {'seq': 29, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 8, 'name': 'django.utils.deprecation', 'path': '/usr/local/lib/python3.7/site-packages/django/utils/deprecation.py', 'package': 'django.utils'}}}
2020-12-01 20:37:22,004 - DEBUG - Message received: {'seq': 30, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 9, 'name': 'lbs.core.middleware', 'path': '/Users/user/Development/app/lbs/core/middleware.py', 'package': 'lbs.core'}}}
2020-12-01 20:37:22,006 - DEBUG - Message received: {'seq': 31, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 10, 'name': 'reversion.middleware', 'path': '/usr/local/lib/python3.7/site-packages/reversion/middleware.py', 'package': 'reversion'}}}
2020-12-01 20:37:22,007 - DEBUG - Message received: {'seq': 32, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 11, 'name': 'whitenoise.middleware', 'path': '/usr/local/lib/python3.7/site-packages/whitenoise/middleware.py', 'package': 'whitenoise'}}}
2020-12-01 20:37:22,007 - DEBUG - Message received: {'seq': 33, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 12, 'name': 'channels.http', 'path': '/usr/local/lib/python3.7/site-packages/channels/http.py', 'package': 'channels'}}}
2020-12-01 20:37:22,008 - DEBUG - Message received: {'seq': 34, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 13, 'name': 'asgiref.sync', 'path': '/usr/local/lib/python3.7/site-packages/asgiref/sync.py', 'package': 'asgiref'}}}
2020-12-01 20:37:22,009 - DEBUG - Message received: {'seq': 35, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 14, 'name': 'concurrent.futures.thread', 'path': '/usr/local/lib/python3.7/concurrent/futures/thread.py', 'package': 'concurrent.futures'}}}
2020-12-01 20:37:22,010 - DEBUG - Message received: {'seq': 36, 'type': 'event', 'event': 'module', 'body': {'reason': 'new', 'module': {'id': 15, 'name': 'threading', 'path': '/usr/local/lib/python3.7/threading.py'}}}
2020-12-01 20:37:22,025 - DEBUG - Message received: {'seq': 37, 'type': 'response', 'request_seq': 9, 'success': True, 'command': 'scopes', 'body': {'scopes': [{'name': 'Locals', 'variablesReference': 8, 'expensive': False, 'presentationHint': 'locals', 'source': {}}, {'name': 'Globals', 'variablesReference': 9, 'expensive': False, 'source': {}}]}}
2020-12-01 20:37:22,025 - DEBUG - Sending Message: {"command": "variables", "arguments": {"variablesReference": 8}, "seq": 10, "type": "request"}
2020-12-01 20:37:22,368 - DEBUG - Message received: {'seq': 38, 'type': 'response', 'request_seq': 10, 'success': True, 'command': 'variables', 'body': {'variables': [{'name': 'self', 'value': '<lbs.api_internal.things.viewsets.thing.ObjectViewSet object at 0x7f02504a6a90>', 'type': 'ObjectViewSet', 'evaluateName': 'self', 'variablesReference': 10}]}}
2020-12-01 20:55:08,960 - DEBUG - Stop debug adapter with no callback
2020-12-01 20:55:08,961 - DEBUG - Sending Message: {"command": "disconnect", "arguments": {}, "seq": 11, "type": "request"}
2020-12-01 20:55:09,002 - DEBUG - Message received: {'seq': 39, 'type': 'event', 'event': 'terminated'}
2020-12-01 20:55:09,002 - INFO - User Msg: Debugging was terminated by the server.
2020-12-01 20:55:09,003 - DEBUG - Message received: {'seq': 40, 'type': 'response', 'request_seq': 11, 'success': True, 'command': 'disconnect'}
2020-12-01 20:55:09,052 - INFO - The server has terminated with status 0
2020-12-01 20:55:09,053 - DEBUG - No server exit handler
int19h commented 3 years ago

I don't think there's anything about the "process" event that you'd need for this. It's only reported for the process that is being debugged in that particular session, always at the very beginning of it, and it seems to be purely informational. Even for process tree UX - if you choose to implement it similarly to how VSCode does - all the requisite info is in the "debugpyAttach" event.

puremourning commented 3 years ago

Thanks 🙏

Frederick888 commented 3 years ago

I'd like to have multiple debugging sessions at the same time as well for a different reason: I've got multiple Java applications in the same 'workspace' root (not sure if this is the correct word) and they communicate with each other through API requests and/or queues. Hence it'll be extremely handy if vimspector can attach to multiple applications simultaneously and set breakpoints in different sub-projects.

May I know whether my request is the same as this one or I should open a new ticket?

(Originally reported at dansomething/coc-java-debug#16)

puremourning commented 3 years ago

May I know whether my request is the same as this one or I should open a new ticket?

It's essentially the same. Another issue won't make it come any faster.

roachsinai commented 3 years ago

Yep, the way DAP is structured, every process has to be its own separate session. On debugpy side, when subprocess is detected and detoured, we send a custom event that basically contains the body of the "attach" event that is necessary to attach to that subprocess - the client has to handle that accordingly.

We are hoping to submit this sort of "reverse attach request" for standardization in the main protocol eventually. But that will only happen after this custom implementation had some time to prove that it's a solid approach.

Can't wait for this but have to wait, lol.

puremourning commented 1 year ago

For anyone tracking this, this should now work in the PR in #748 ; feel free to try it:

Screenshot 2023-04-12 at 15 05 22 Screenshot 2023-04-12 at 15 05 41
gagara commented 1 year ago

Thanks a lot. Does it also implements https://github.com/puremourning/vimspector/issues/141#issuecomment-745255008 ?

puremourning commented 1 year ago

Thanks a lot. Does it also implements https://github.com/puremourning/vimspector/issues/141#issuecomment-745255008 ?

No not yet

puremourning commented 1 year ago

Thanks a lot. Does it also implements #141 (comment) ?

This is implemented in pr #756; feel free to check it out.