Can't break in the attach mode
NOTE: Before submitting an issue, please make sure to install the latest version of both the vscode extension and the R package. This can usually be achieved by running the command r.debugger.updateRPackage in vscode's command palette (F1).
Describe the bug Can't make VSCode stop at breakpoints upon attaching to the R process as documented in https://github.com/ManuelHentschel/vscDebugger/blob/master/vignettes/vscode-R-Debugger.Rmd#L65.
To Reproduce Steps to reproduce the behavior:
- Execute the following R code:
library(vscDebugger)
print('Started listening for debugging connections...')
.vsc.listen()
print('Got a debugging connection...')
Sys.sleep(5)
.vsc.debugSource('file.R')
print('Finished executingR')
- When the R script execution reaches
.vsc.debugSource('file.R')start the R debugger with the following configuration:
{
"type": "R-Debugger",
"name": "Attach to R process",
"request": "attach",
"useCustomSocket": true
},
- In VSCode, set manually some debugging points in
file.R - Hit the 'Continue' button so the debugger proceeds stepping through the code
- The debugger doesn't stop at any breakpoints defined in step 3.
Your R code
library(vscDebugger)
print('Started listening for debugging connections...')
.vsc.listen()
print('Got a debugging connection...')
Sys.sleep(5)
.vsc.debugSource('file.R')
print('Finished executingR')
Your Launch config
{
"type": "R-Debugger",
"name": "Attach to R process",
"request": "attach",
"useCustomSocket": true
},
Expected behavior The debugger should stop at any breakpoint defined in file.R in VSCode.
Actual behavior The debugger just executes the file without stopping at any breakpoints.
Desktop (please complete the following information):
- OS:
Ubuntu 22 - R Version:
4.1.2 - vscDebugger Version:
0.5.5 - vscode-r-debugger Version:
0.5.3
Additional context
Not sure if I need to use Sys.sleep(5)? Perhaps that line could be removed. Also do I need to use "useCustomSocket": true?
Hi. The attach mode is a bit limited, in particular when it comes to flow control (stepping through code). In https://github.com/ManuelHentschel/vscDebugger/commit/a305755f1afd038092e82b9bd99d8559737ae7b2 I added a missing call to .vsc.listen(), with this change the expected behavior for your scenario would be:
Run the following in a terminal:
library(vscDebugger)
.vsc.listen()
then launch the debug config
{
"type": "R-Debugger",
"name": "Attach to R process",
"request": "attach",
"useCustomSocket": true
},
The debugger should now connect to your session, showing a Global Workspace frame in the call stack. You can now run R commands in the debug console. In the original terminal, the call to .vsc.listen() is blocking, i.e. you cannot run any commands there while the debugger is attached. You might see some output from your code in the debug console though.
Calling .vsc.debugSource is a bit of a special case. With the fix mentioned above, and if your terminal is an integrated vscode terminal, hitting breakpoints and stepping through the code should work (at least in simple examples). However, once you exit the code from file.R, the vscDebugger extension seems to get confused and you have to disconnect, call .vsc.listen(), and attach again. The problematic code is quite messy, so I'm probably not going to be able to fix it soon. I added a note to https://github.com/ManuelHentschel/VSCode-R-Debugger/blob/master/configuration.md#32-attach-requests, though, for what it's worth.
Thanks, now I'm able to debug my code using the interactive R terminal.
But I can't make Rscript to work as well. See the gif below. I'm attaching the debugger to Rscript main.R (main.R calls .vsc.listen()) but the it doesn't stop at any breakpoint.
To be very precise, what I'm trying to achieve is to add a 'debug test' feature to the R Test Adapter extension. This can't be done in the interactive R terminal as I want automate all the process (eliminate any need for user interaction).
I imagine the R Test Adapter should spawn an R process, load vscDebugger and cal .vsc.debugSource. I'm at this stage: RScript -e 'library(vscDebugger); .vsc.listen()'. What should happen next? I imagine I should somehow send the .vsc.debugSource('test_file.R') command to the socket. Could you hint me how to do that?
If this requires additional implementation and you don't have time to work on it, could you give me general tips how to achieve that? Perhaps I could work on this as I already have some development+debugging setup for vscDebugger and I am able to modify its code locally.
That sounds like an interesting idea! Unfortunately, I think this would require a significant amount of work to get working cleanly.
One issue is that browser() does not seem to work in non-interactive mode. You can test this by creating a file that calls a function which contains a browser() call. In interactive mode (e.g. calling source() from inside a normal R session) this lets you step through said function. In non-interactive mode (e.g. Rscript or R -f ...), this will show some browser output, but just continue running as if you pressed c or n repeatedly. However, we need browser() to set breakpoints and (more crucially) to step through the code line-by-line; for instance I am not aware of any other method to "step over", other than typing n in a browser prompt.
This problem could be avoided by running the code in interactive mode, where the debugger extension has control of stdin/stdout/stderr (that's how the "launch" debug mode works). Even then, the biggest challenge I see is how to combine the different "non-standard code execution methods", error handling, and output redirections of the debugger, the testthat framework, and the test-adapter framework. For a related (but simpler) problem on breakpoints in tests, see for example https://github.com/ManuelHentschel/VSCode-R-Debugger/issues/187.
One way to get a limited "debug tests" functionality working might be to create a temporary file that executes the test(s) you want to debug, and then run the debugger with a launch request for that file. This hands over flow control to the debugger, but you might be able to get some result reporting, e.g. by redirecting the output from the reporter to a different socket or file, or by analysing the output messages with a vscode.DebugAdapterTracker.
Thanks for the tips. I started looking into the "interactive R session +stdin/stdout/stderr redirection" variant. I think that a clean implementation would require your VSCode R Debugger extension be exposed as an npm package (including e.g. the RSession class). Unfortunately, I have little experience in typescript. Is such refactor even worth the time?