Race condition: continued event is received while self:update_threads is running. The thread is marked as not stopped but after self:update_threads is done, event_stopped is resumed and thread is incorrectly marked as stopped. This causes "Thread 1 is not paused" error to be shown to user.
Relevant code:
function Session:event_stopped(stopped)
require("dap.async").run(function()
local co = coroutine.running()
if self.dirty.threads or (stopped.threadId and self.threads[stopped.threadId] == nil) then
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
end
local should_jump = stopped.reason ~= 'pause' or stopped.allThreadsStopped
-- Some debug adapters allow to continue/step via custom REPL commands (via evaluate)
-- That by-passes `clear_running`, resulting in self.stopped_thread_id still being set
-- Dont auto-continue if`threadId == self.stopped_thread_id`, but stop & jump
if self.stopped_thread_id and self.stopped_thread_id ~= stopped.threadId and should_jump then
if defaults(self).auto_continue_if_many_stopped then
local thread = self.threads[self.stopped_thread_id]
local thread_name = thread and thread.name or self.stopped_thread_id
log.debug(
'Received stopped event, but ' .. thread_name .. ' is already stopped. ' ..
'Resuming newly stopped thread. ' ..
'To disable this set the `auto_continue_if_many_stopped` option to false.')
self:request('continue', { threadId = stopped.threadId }, function() end)
return
else
-- Allow thread to stop, but don't jump to it because stepping
-- interleaved between threads is confusing
should_jump = false
end
end
if should_jump then
self.stopped_thread_id = stopped.threadId
end
if stopped.allThreadsStopped then
progress.report('All threads stopped')
for _, thread in pairs(self.threads) do
thread.stopped = true
end
elseif stopped.threadId then
progress.report('Thread stopped: ' .. stopped.threadId)
self.threads[stopped.threadId].stopped = true
else
utils.notify('Stopped event received, but no threadId or allThreadsStopped', vim.log.levels.WARN)
end
Debug adapter definition and debug configuration
No response
Debug adapter version
No response
Steps to Reproduce
After https://github.com/mfussenegger/nvim-dap/issues/1363 got merged another race condition became apparent.
Related issue: https://github.com/dart-lang/sdk/issues/57006
Race condition:
continued
event is received whileself:update_threads
is running. The thread is marked as not stopped but afterself:update_threads
is done,event_stopped
is resumed and thread is incorrectly marked as stopped. This causes "Thread 1 is not paused" error to be shown to user.Relevant code:
Logs with addtional custom added `--> ` events
``` [ DEBUG ] 2024-11-15T18:43:22Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1455 ] "Spawning debug adapter" { args = { "debug-adapter" }, command = "/Users/ts/fvm/versions/3.24.5/bin/flutter", type = "executable" } [ DEBUG ] 2024-11-15T18:43:22Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1767 ] "request" { arguments = { adapterID = "nvim-dap", clientID = "neovim", clientName = "neovim", columnsStartAt1 = true, linesStartAt1 = true, locale = "en_US.UTF-8", pathFormat = "path", supportsProgressReporting = true, supportsRunInTerminalRequest = true, supportsStartDebuggingRequest = true, supportsVariableType = true }, command = "initialize", seq = 1, type = "request" } [ DEBUG ] 2024-11-15T18:43:23Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { exceptionBreakpointFilters = { { default = false, filter = "All", label = "All Exceptions" }, { default = true, filter = "Unhandled", label = "Uncaught Exceptions" } }, supportsClipboardContext = true, supportsConditionalBreakpoints = true, supportsConfigurationDoneRequest = true, supportsDelayedStackTraceLoading = true, supportsEvaluateForHovers = true, supportsLogPoints = true, supportsRestartFrame = true, supportsRestartRequest = false, supportsTerminateRequest = true, supportsValueFormattingOptions = true }, command = "initialize", request_seq = 1, seq = 1, success = true, type = "response" } [ DEBUG ] 2024-11-15T18:43:23Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1767 ] "request" { arguments = { args = {}, cwd = "/Users/ts/Documents/github/personal/tmp/create-new/test", dartSdkPath = "/Users/ts/fvm/versions/3.24.5/bin/cache/dart-sdk", debugExternalPackageLibraries = false, debugSdkLibraries = false, evaluateToStringInDebugViews = true, flutterSdkPath = "/Users/ts/fvm/versions/3.24.5", name = "Launch flutter", program = "lib/main.dart", request = "launch", type = "dart" }, command = "launch", seq = 2, type = "request" } [ DEBUG ] 2024-11-15T18:43:23Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = vim.empty_dict(), event = "initialized", seq = 2, type = "event" } [ DEBUG ] 2024-11-15T18:43:23Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1767 ] "request" { arguments = { filters = {} }, command = "setExceptionBreakpoints", seq = 3, type = "request" } [ DEBUG ] 2024-11-15T18:43:23Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = vim.empty_dict(), command = "setExceptionBreakpoints", request_seq = 3, seq = 3, success = true, type = "response" } [ DEBUG ] 2024-11-15T18:43:23Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1767 ] "request" { command = "configurationDone", seq = 4, type = "request" } [ DEBUG ] 2024-11-15T18:43:23Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { command = "configurationDone", request_seq = 4, seq = 4, success = true, type = "response" } [ DEBUG ] 2024-11-15T18:43:23Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { message = "Launching…", progressId = "launch_1", title = "Flutter" }, event = "progressStart", seq = 5, type = "event" } [ DEBUG ] 2024-11-15T18:43:23Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { command = "launch", request_seq = 2, seq = 6, success = true, type = "response" } [ DEBUG ] 2024-11-15T18:43:27Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { capabilities = { supportsRestartRequest = true } }, event = "capabilities", seq = 7, type = "event" } [ DEBUG ] 2024-11-15T18:43:27Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { appId = "071e63f8-4597-447f-8b1d-13d20dcb7a20", deviceId = "F98BFF5F-1F19-4CE5-B56C-2E5A40B6FB09", directory = "/Users/ts/Documents/github/personal/tmp/create-new/test", launchMode = "run", mode = "debug", supportsRestart = true }, event = "flutter.appStart", seq = 8, type = "event" } [ WARN ] 2024-11-15T18:43:27Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1084 ] "No event handler for " { body = { appId = "071e63f8-4597-447f-8b1d-13d20dcb7a20", deviceId = "F98BFF5F-1F19-4CE5-B56C-2E5A40B6FB09", directory = "/Users/ts/Documents/github/personal/tmp/create-new/test", launchMode = "run", mode = "debug", supportsRestart = true }, event = "flutter.appStart", seq = 8, type = "event" } [ DEBUG ] 2024-11-15T18:43:27Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { category = "console", output = "Launching lib/main.dart on iPhone 14 in debug mode...\n" }, event = "output", seq = 9, type = "event" } [ DEBUG ] 2024-11-15T18:43:29Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { message = "Running Xcode build...", progressId = "launch_1" }, event = "progressUpdate", seq = 10, type = "event" } [ DEBUG ] 2024-11-15T18:43:44Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { category = "console", output = "Xcode build done. 14.6s\n" }, event = "output", seq = 11, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { message = "Syncing files to device iPhone 14...", progressId = "launch_1" }, event = "progressUpdate", seq = 12, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { progressId = "launch_1" }, event = "progressEnd", seq = 13, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { output = "Connecting to VM Service at ws://127.0.0.1:64933/z46_aWfDgng=/ws\n" }, event = "output", seq = 14, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { output = "Connected to the VM Service.\n" }, event = "output", seq = 15, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { vmServiceUri = "ws://127.0.0.1:64933/z46_aWfDgng=/ws" }, event = "dart.debuggerUris", seq = 16, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { reason = "started", threadId = 1 }, event = "thread", seq = 17, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { reason = "entry", threadId = 1 }, event = "stopped", seq = 18, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:689 ] "--> Session:event_stopped(stopped), self.threads" { reason = "entry", threadId = 1 } { { id = 1, name = "Unknown" } } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:694 ] "--> Session:event_stopped self.dirty.threads" true [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1767 ] "request" { command = "threads", seq = 5, type = "request" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = vim.empty_dict(), event = "flutter.appStarted", seq = 19, type = "event" } [ WARN ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1084 ] "No event handler for " { body = vim.empty_dict(), event = "flutter.appStarted", seq = 19, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { method = "s0.reloadSources", service = "reloadSources" }, event = "dart.serviceRegistered", seq = 20, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { method = "s0.hotRestart", service = "hotRestart" }, event = "dart.serviceRegistered", seq = 21, type = "event" } [ WARN ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1084 ] "No event handler for " { body = { method = "s0.reloadSources", service = "reloadSources" }, event = "dart.serviceRegistered", seq = 20, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { method = "s0.flutterVersion", service = "flutterVersion" }, event = "dart.serviceRegistered", seq = 22, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { method = "s0.compileExpression", service = "compileExpression" }, event = "dart.serviceRegistered", seq = 23, type = "event" } [ WARN ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1084 ] "No event handler for " { body = { method = "s0.hotRestart", service = "hotRestart" }, event = "dart.serviceRegistered", seq = 21, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { method = "s0.flutterMemoryInfo", service = "flutterMemoryInfo" }, event = "dart.serviceRegistered", seq = 24, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { method = "s0.flutterGetSkSL", service = "flutterGetSkSL" }, event = "dart.serviceRegistered", seq = 25, type = "event" } [ WARN ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1084 ] "No event handler for " { body = { method = "s0.flutterVersion", service = "flutterVersion" }, event = "dart.serviceRegistered", seq = 22, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { threadId = 1 }, event = "continued", seq = 26, type = "event" } [ WARN ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1084 ] "No event handler for " { body = { method = "s0.compileExpression", service = "compileExpression" }, event = "dart.serviceRegistered", seq = 23, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { threads = { { id = 1, name = "main" } } }, command = "threads", request_seq = 5, seq = 27, success = true, type = "response" } [ WARN ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1084 ] "No event handler for " { body = { method = "s0.flutterMemoryInfo", service = "flutterMemoryInfo" }, event = "dart.serviceRegistered", seq = 24, type = "event" } [ WARN ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1084 ] "No event handler for " { body = { method = "s0.flutterGetSkSL", service = "flutterGetSkSL" }, event = "dart.serviceRegistered", seq = 25, type = "event" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1962 ] "--> Session:event_continued(event), self.thread" { threadId = 1 } { { id = 1, name = "Unknown" } } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1979 ] "--> Session:event_continued(event) after, self.thread" { { id = 1, name = "Unknown" } } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:664 ] "--> Session:update_threads before update self.threads.threads" { { id = 1, name = "Unknown" } } { { id = 1, name = "main" } } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:751 ] "--> Session:event_stopped before stacktrace; thread, self.threads" { id = 1, name = "main", stopped = true } { { id = 1, name = "main", stopped = true } } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1767 ] "request" { arguments = { startFrame = 0, threadId = 1 }, command = "stackTrace", seq = 6, type = "request" } [ DEBUG ] 2024-11-15T18:43:46Z+0200 ] ...ments/github/personal/forks/nvim-dap/lua/dap/session.lua:1034 ] 1 { body = { error = { format = "{message}", id = 1, showUser = true, variables = { message = "Thread 1 is not paused", stack = "#0 DartDebugAdapter.stackTraceRequest (package:dds/src/dap/adapters/dart.dart:1847:7)\n#1 BaseDebugAdapter.handle (package:dds/src/dap/base_debug_adapter.dart:141:20)\n#2 BaseDebugAdapter.handleIncomingRequest (package:dds/src/dap/base_debug_adapter.dart:440:7)\n#3 BaseDebugAdapter._handleIncomingMessage (package:dds/src/dap/base_debug_adapter.dart:309:7)\n#4 ByteStreamServerChannel._readMessage (package:dds/src/dap/protocol_stream.dart:82:18)\n#5 ByteStreamServerChannel.listen.Expected Result
"Thread 1 is not paused" should not be shown to the user. Resumed thread should not be marked as stopped.
Actual Result
"Thread 1 is not paused" is shown to the user.