Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Won't terminate after the first encountered breakpoint on vscode-js-debug #1166

Open
foxt451 opened this issue Feb 29, 2024 · 9 comments
Open

Comments

@foxt451
Copy link

foxt451 commented Feb 29, 2024

Debug adapter definition and debug configuration

{
"microsoft/vscode-js-debug",
build = "npm install --legacy-peer-deps && npx gulp dapDebugServer && mv dist out",
}

{
"mfussenegger/nvim-dap",
dependencies = {
"microsoft/vscode-js-debug",
},
config = function()
require("dap").adapters["pwa-node"] = {
type = "server",
host = "localhost",
port = "${port}",
executable = {
command = "node",
args = {
vim.call("stdpath", "data") .. "/lazy/vscode-js-debug/out/src/dapDebugServer.js",
"${port}",
},
}
}
for _, language in ipairs({ "typescript", "javascript" }) do
require("dap").configurations[language] = {
{
type = "pwa-node",
name = "Node",
request = "launch",
program = "${file}",
cwd = "${workspaceFolder}",
console = "integratedTerminal",
skipFiles = {
"<node_internals>/",
"${workspaceFolder}/node_modules/
"
},
},
}
end

Debug adapter version

vscode-js-debug - latest commit 1e5bf60; nvim-dap - too

Steps to Reproduce

  1. Open this code:
console.log('Hello, world!');
 await new Promise((resolve) => setTimeout(resolve, 5000));
 console.log('Hello, world!'); // <---------------------BREAKPOINT HERE
 await new Promise((resolve) => setTimeout(resolve, 5000));
 console.log('Hello, world!'); 
  1. Try to terminate during first await - the process exits
  2. Then restart, stop on first breakpoint, continue, and terminate on the second await - nothing happens

Expected Result

Process terminates successfully during the second await too

Actual Result

Nothing happens when terminating during the second await

@foxt451 foxt451 changed the title ### Debug adapter definition and debug configuration _No response_ ### Debug adapter version latest - commit 1e5bf60 ### Steps to Reproduce Debug adapter definition and debug configuration Feb 29, 2024
@foxt451 foxt451 changed the title Debug adapter definition and debug configuration Won't terminate after the first encountered breakpoint on vscode-js-debug Feb 29, 2024
@foxt451
Copy link
Author

foxt451 commented Mar 4, 2024

I've delved a bit more into it and I can actually terminate the debuggee after the first breakpoint with firing 3 terminate commands (and in case of the second breakpoint too). I don't think this is expected... The terminate requests have to occur with some delay in between

Btw, node version doesn't seem to matter

@mfussenegger
Copy link
Owner

vscode-js-debug starts multiple sub-sessions and terminate currently only terminates the active session.
The multi-session feature is unfortunately a bit underspecified in the spec. E.g. debugpy uses it too for python multiprocessing, and there I haven't noticed that it's necessary to terminate multiple times. But I think it might be reasonable to broadcast a terminate to all children of a session.

You can see the sessions using something like:

:lua local w = require("dap.ui.widgets"); w.sidebar(w.sessions, {}, '5 sp').toggle()

@foxt451
Copy link
Author

foxt451 commented Mar 5, 2024

Thanks! Do you imagine some clean way of terminating all the children as well?
I tried this:

      {
        "<leader>dt",
        function()
          require("dap").terminate()
          local all_sessions = require("dap").sessions()
          for _, session in ipairs(all_sessions) do
            session:disconnect({
              terminateDebuggee = true
            })
          end
        end,
        desc = "Terminate"
      },

(and without require("dap").terminate() and with the order swapped)
but when I start the previous debug configuration again, it will either not react to dt at all, or disconnect without temrinating debugee, or the terminal is empty, or it doesn't continue after the breakpoint, depending on the order of the statements

@maxbol
Copy link

maxbol commented May 8, 2024

+1 for this experience not being very good, whether or not it is in the scope of nvim-dap to fix it...

@maxbol
Copy link

maxbol commented May 8, 2024

Interestingly, I was experience the same "three strikes" behavior as you did @foxt451 , but if I open up the sessions list as described by @mfussenegger and then selecting the top level session before running terminate(), the debugger and debuggee both immediately terminate. So if there was some way of programatically finding out which the top level session is, switching to it as the active one, and running terminate, that would likely fix the issue.

@maxbol
Copy link

maxbol commented May 8, 2024

The following hackish bind solves the issue for me right now. If someone can tell me how to actually tell it to set the top level session of the branch that I'm currently on, and not just the first best one, that would be awesome!

         {
		"<leader>dt",
		function()
			local dap = require("dap")

			local session_to_activate = nil
			local sessions = dap.sessions()

			for _, s in pairs(sessions) do
				session_to_activate = s
				break
			end

			if session_to_activate ~= nil then
				dap.set_session(session)
			end

			dap.terminate()
		end,
		desc = "Terminate",
	}

@mfussenegger
Copy link
Owner

Could you try with:

local dap = require("dap")
local session = dap.session()
if session and session.parent then
    dap.set_session(session.parent)
end
dap.terminate()

Doing this implicitly within terminate() could be an option

@maxbol
Copy link

maxbol commented May 8, 2024

Cool, didn't know about session.parent! Will try.

How about if the focused session is more than one level deep? Maybe a while loop to traverse until session.parent is nil? Not sure if this is a real world case though (but I know that these things go more than one level deep with JS, but it seems to always break at the 1-level deep session)

@maxbol
Copy link

maxbol commented May 8, 2024

Btw, how would you recommend setting a bind to terminate ALL sessions?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants