code-debug icon indicating copy to clipboard operation
code-debug copied to clipboard

Native Debug executes `-thread-info` after `-exec-continue`

Open desertkun opened this issue 2 years ago • 4 comments

While developing a custom gdb with mi/2 protocol, I've noticed that Native Debug for some reason tries to obtain some thread info after doing continue (after connecting to remote target):

....
6-exec-continue
GDB -> App: {"token":6,"outOfBandRecord":[],"resultRecords":{"resultClass":"running","results":[]}}
GDB -> App: {"outOfBandRecord":[{"isStream":false,"type":"exec","asyncClass":"running","output":[["thread-id","all"]]}]}
7-stack-info-depth --thread 1
GDB -> App: {"token":7,"outOfBandRecord":[],"resultRecords":{"resultClass":"error","results":[["msg","A program is running.\n"]]}}
8-thread-info
GDB -> App: {"token":8,"outOfBandRecord":[],"resultRecords":{"resultClass":"error","results":[["msg","A program is running.\n"]]}}
9-thread-info
GDB -> App: {"token":9,"outOfBandRecord":[],"resultRecords":{"resultClass":"error","results":[["msg","A program is running.\n"]]}}

I am experiencing this myself, but unable to provide a repro since my debugger is too unique, but I've noticed similar bugs like here or here with the same pattern: continue or run might have a follow up command that lags behind.

While original issues there might have been resolved, issuing thread-state commands after continue seems like a bug, which forces me to error out, which give those annoying popups.

What is the workaround here? When mi/2 is asked to continue, continue like after 100ms so lagging commands would have a chance to execute?

desertkun avatar Jun 09 '22 23:06 desertkun

Are those commands actually lagging? The commands themselves get in later. It looks like the right option is to keep a "is running" state variable (if we don't have it yet) and check that before asking for thread info.

GitMensch avatar Jun 10 '22 06:06 GitMensch

Every command has sequence prepended to it, so clearly it continues first and then gets thread info. I've tested it on regular gdb, after executing continue it doesn't give any response for thread info command. Some other implementations give an error, like mine.

So with running variable, what is going to happen to those requests past continue, are they just going to fail? I suspected there some sort of concurrency issue but it doesn't seem like it.

I really want to support vscode in my debugger but can't comprehend the behavior.

desertkun avatar Jun 10 '22 09:06 desertkun

As previously mentioned, there is currently no state information kept by Native Debug to know when the application is running or stopped. The "thread info" commands are initiated by the editor (e.g., VSCode) based on having previously received an indication that the application being debugged has stopped. With gdb, this typically happens as soon as you start the debugger.

The debug adapter (i.e., Native Debug) is configured to either continue execution or stopAtConnect. Therefore, this happens when Native Debug is configured to continue execution after startup (the default state). Under this configuration, the debugger is commanded to continue running, but then the "thread info" commands are sent from the editor to Native Debug which then forwards them on to the debugger, causing this issue.

I think with the current design, you can encounter this situation any time there is a stop followed by a continue shortly after, so the state between the editor and the debugger become out-of-sync. When the application is stopped, the editor will interrogate the thread status, gather stack frames and local variable data. Do you see this happen in any other situation other than at startup? I know that is the most likely place to happen.

I think one approach, short of trying to manage the running status for all commands is to add special logic to handle the startup situation. Native Debug could prevent the "stopped" status from the debugger from being sent to the editor if it knows that it has been configured to continue execution. In that way, I think this would likely address the situation at startup. I'm not sure how likely this is to happen at other points during a debug session though.

brownts avatar Jun 10 '22 12:06 brownts

Thanks for thorough explanation @brownts, yeah with stopAtConnect the problem goes away, I guess I can ask users of my gdb to turn that on for the time being.

Otherwise, I like the idea of skipping "stopped" propagation, as I am only experiencing this on startup, however, I am not fit for any kind of typescript work. Could you please (if you're familiar) take a look at that, or maybe point to someone who can?

desertkun avatar Jun 10 '22 18:06 desertkun