Skip to content

Commit cc92b05

Browse files
committed
Fix race between stopped thread retrieval and continued event
If the debug adapter sends continued right after stopped, before the client retrieved the threads the continued change was lost. Should fix #1365
1 parent 29d1f88 commit cc92b05

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

lua/dap/session.lua

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,8 @@ function Session:update_threads(cb)
657657
threads[thread.id] = thread
658658
local old_thread = self.threads[thread.id]
659659
if old_thread then
660-
thread.stopped = old_thread.stopped
660+
local stopped = old_thread.stopped == nil and false or old_thread.stopped
661+
thread.stopped = stopped
661662
thread.frames = old_thread.frames
662663
end
663664
end
@@ -689,12 +690,24 @@ function Session:event_stopped(stopped)
689690
local co = coroutine.running()
690691

691692
if self.dirty.threads or (stopped.threadId and self.threads[stopped.threadId] == nil) then
693+
local thread = {
694+
id = stopped.threadId,
695+
name = "Unknown",
696+
stopped = true
697+
}
698+
if thread.id then
699+
self.threads[thread.id] = thread
700+
end
692701
self:update_threads(coresume(co))
693702
local err = coroutine.yield()
694703
if err then
695704
utils.notify('Error retrieving threads: ' .. utils.fmt_error(err), vim.log.levels.ERROR)
696705
return
697706
end
707+
if thread.stopped == false then
708+
log.debug("Thread resumed during stopped event handling", stopped, thread)
709+
return
710+
end
698711
end
699712

700713
local should_jump = stopped.reason ~= 'pause' or stopped.allThreadsStopped

spec/integration_spec.lua

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,32 @@ describe('dap with fake server', function()
322322
})
323323
end)
324324

325+
it("Doesn't jump on stopped if continue is received before threads response", function()
326+
run_and_wait_until_initialized(config, server)
327+
server.client.threads = function(self, request)
328+
self:send_event("continued", {
329+
threadId = 1,
330+
})
331+
self:send_response(request, {
332+
threads = { { id = 1, name = 'thread1' }, }
333+
})
334+
end
335+
local log = require('dap.log').create_logger('dap.log')
336+
local debug = log.debug
337+
local messages = {}
338+
log.debug = function(...)
339+
table.insert(messages, {...})
340+
debug(...)
341+
end
342+
server.client:send_event('stopped', {
343+
threadId = 1,
344+
reason = 'unknown',
345+
})
346+
wait_for_response(server, "threads")
347+
wait(function() return #messages >= 5 end)
348+
assert.are.same("Thread resumed during stopped event handling", messages[6][1])
349+
end)
350+
325351
it("Clears stopped state on continued event", function()
326352
local buf = api.nvim_create_buf(true, false)
327353
local win = api.nvim_get_current_win()

0 commit comments

Comments
 (0)