Skip to content

Commit

Permalink
Fix race between stopped thread retrieval and continued event
Browse files Browse the repository at this point in the history
If the debug adapter sends continued right after stopped, before the
client retrieved the threads the continued change was lost.

Should fix #1365
  • Loading branch information
mfussenegger committed Nov 18, 2024
1 parent 29d1f88 commit cc92b05
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
15 changes: 14 additions & 1 deletion lua/dap/session.lua
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,8 @@ function Session:update_threads(cb)
threads[thread.id] = thread
local old_thread = self.threads[thread.id]
if old_thread then
thread.stopped = old_thread.stopped
local stopped = old_thread.stopped == nil and false or old_thread.stopped
thread.stopped = stopped
thread.frames = old_thread.frames
end
end
Expand Down Expand Up @@ -689,12 +690,24 @@ function Session:event_stopped(stopped)
local co = coroutine.running()

if self.dirty.threads or (stopped.threadId and self.threads[stopped.threadId] == nil) then
local thread = {
id = stopped.threadId,
name = "Unknown",
stopped = true
}
if thread.id then
self.threads[thread.id] = thread
end
self:update_threads(coresume(co))
local err = coroutine.yield()
if err then
utils.notify('Error retrieving threads: ' .. utils.fmt_error(err), vim.log.levels.ERROR)
return
end
if thread.stopped == false then
log.debug("Thread resumed during stopped event handling", stopped, thread)
return
end
end

local should_jump = stopped.reason ~= 'pause' or stopped.allThreadsStopped
Expand Down
26 changes: 26 additions & 0 deletions spec/integration_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,32 @@ describe('dap with fake server', function()
})
end)

it("Doesn't jump on stopped if continue is received before threads response", function()
run_and_wait_until_initialized(config, server)
server.client.threads = function(self, request)
self:send_event("continued", {
threadId = 1,
})
self:send_response(request, {
threads = { { id = 1, name = 'thread1' }, }
})
end
local log = require('dap.log').create_logger('dap.log')
local debug = log.debug
local messages = {}
log.debug = function(...)
table.insert(messages, {...})
debug(...)
end
server.client:send_event('stopped', {
threadId = 1,
reason = 'unknown',
})
wait_for_response(server, "threads")
wait(function() return #messages >= 5 end)
assert.are.same("Thread resumed during stopped event handling", messages[6][1])
end)

it("Clears stopped state on continued event", function()
local buf = api.nvim_create_buf(true, false)
local win = api.nvim_get_current_win()
Expand Down

0 comments on commit cc92b05

Please sign in to comment.