How to run VSCode launch debug commands after the -exec-run point? - visual-studio-code

I've created a VSCode launch.json configuration that can invoke my program, set some breakpoints and stop at the main breakpoint:
{
"version": "0.2.0",
"configurations": [
{
"name": "(lldb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "/usr/bin/foo",
"args": ["--debug", "-j", "${fileDirname}/${fileBasenameNoExtension}.xxx"],
"stopAtEntry": true,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "lldb",
"miDebuggerPath": "/usr/bin/lldb-mi",
//"logging": {
// "trace": true,
// "traceResponse": true,
// "engineLogging": true
//},
"setupCommands": [
{ "text": "-break-insert -f rc_pli_enter_module" },
{ "text": "-break-insert -f print_message" },
{ "text": "-break-insert -f rc_pli_fatal_error" }
]
}
]
}
I need the pass the following to the debugger:
process handle -s false -n false -p true SIGSEGV
since our code has a complicated SEGV handler that basically needs to be ignored while debugging, however, if I include that 'process handle' in the setupCommands, I get an error:
error: invalid target, create a target using the 'target create' command
I see in the debug-console log (when enabled) that all these setupCommands run before VSCode sends it's commands to the MI client that get the target actually running. i.e.:
-environment-cd /home/pjoot/...
-file-exec-and-symbols /usr/bin/foo
-exec-arguments --debug -j /home/pjoot/yyy.xxx
-exec-run
If I try putting those target commands into my setupCommands then I can get my 'process handle' to run after the main breakpoint, but VSCode will then try to do that itself and things get confused (it doesn't like the threads output that it gets back prior to it's own target-create processing.)
Is there something like setupCommands that I can use to have VSCode send additional MI commands after the 'target create' processing is done?
I know that I can do this manually in the debug-console using:
-exec process handle -s false -n false -p true SIGSEGV
but it would be nicer to not have to remember that long command, and instead run that (+continue to my real non-main breakpoint) automatically.
EDIT: I found the postRemoteConnectCommands option (that doesn't seem to be documented, but is mentioned here). I'm able to use this for gdb breakpoints, which don't work in setupCommands without 'set breakpoints pending on' first. However, postRemoteConnectCommands when used with lldb by vscode, still appears to be run before the target is setup.

Related

Start GDB using command line via VSCode launch.json

I'm using GDB to debug a QEMU program using vscode. The GDB server is started by a make command, via a task in tasks.json:
"tasks": [
{
"label": "ARMCM33_GDBServer",
"type": "shell",
"command": "make gdbserver",
"isBackground": true
}
]
Where my makefile looks a bit like this:
gdbserver: $(BINARY)
#$(QEMU_PATH) \
-machine $(MACHINE_NAME) \
-kernel $(BUILD_DIR)/kernel.elf \
-S -gdb tcp::4321
gdb: $(BINARY)
$(GDB) $(BINARY) -ex "target remote:4321"
My launch.json looks a bit like this:
"configurations": [
{
"type": "cppdbg",
"request": "launch",
"name": "Debug",
"miDebuggerPath": "/bin/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-gdb",
"program": "build/ARMCM33/kernel.elf",
"args": ["ex"],
"miDebuggerServerAddress": "localhost:4321",
"preLaunchTask": "ARMCM33_GDBServer",
],
},
This all works well in vscode. However, the problem is I want vscode to use my Makefile gdb call, rather than having to duplicate parameters in the launch.json (e.g. like the TCP address, GDB path). Having browsed the launch.json docs, I can't immediately see a solution.
So, how do I use my gdb command line command to use GDB in vscode?

Run bash script with VS Code

I want to run bash script when I hit F5 and see the results in the terminal like I can do with python scripts or whatever. I tried to do that with Bash Debug however it automatically goes to the debug mode and stops at the first step even if I do not put breakpoint. This is the launch configuration I use.
{
"type": "bashdb",
"request": "launch",
"name": "Run mysql test",
"cwd": "${workspaceFolder}",
"program": "/srv/gpf/dba/mysqlslap/run.sh",
"args": []
}
I don't know about running bash in a debug mode (doesn't seem like you need those features based on your example) but you can easily get your script to run as a Task or Build option.
Place this at .vscode/tasks.json of your project dir
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Run as Bash Script",
"type": "shell",
"command": "/bin/bash ${file}",
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
You can place whatever you want in the "command" parameter.
As you can see, it's of type "kind": "build" so I can hit ctrl+shift+B and this will execute in a terminal.
Note, you can also use the command palette (F1 or ctrl+shift+P) and use Task: Run as Task too.
Source: https://code.visualstudio.com/Docs/editor/tasks

Running a gdb command before attaching it to a process via Visual Studio Code

I am trying to step through Postgresql code using Visual Studio Code as my IDE on Linux. I am using attach to a process config in launch.json to achieve the same. Following is the launch.json config:
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "attach",
"program": "/usr/local/pgsql/bin/postgres",
"processId": 4165,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true,
}
]
}
]
}
When I start Debugging via the GUI, it attaches to the process. But whenever I add a breakpoint, I get the following message printed on the debug console:
Program received signal SIGINT, Interrupt.
0x00007ff5d084e31b in epoll_wait () from /lib64/libc.so.6
And fails to add the breakpoint. From the Postgres developer documentation (link) it is clear that we need to bypass the interrupts arriving at gdb by issuing the following command to gdb:
handle SIGUSR1 noprint pass
I think this command in gdb can be executed only before attaching the process for debugging. Hence when I run this command via the debug console on Visual Studio Code, I get the following error:
Unable to perform this action because the process is running.
Is there a way to instruct the Visual Studio Code debugging, to issue the "handle SIGUSR1 noprint pass" into gdb before it attaches the target process via gdb?
After more research, I found a way to achieve this using ~/.gdbinit file. This file can have commands that will be run each time gdb is run. I have the following content in it:
handle SIGUSR1 nostop noprint pass
handle SIGINT nostop noprint pass
Now what happens is since SIGINT is being overriden, every time the IDE is disconnected from the process, it has be restarted because it cannot disconnect gracefully anymore.
Consider to define these commands in section setupCommands of launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "debugging of local server",
"type": "cppdbg",
"request": "attach",
"program": "/usr/local/pgsql/bin/postgres",
"processId": "${command:pickProcess}",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "ignore SIGUSR1 signal",
"text": "handle SIGUSR1 nostop noprint pass"
}
]
}
]
}
In addition to Keshav's answer.
You may also add another command to the ~/.gdbinit file :
set auto-load safe-path /
This will tell the compiler that it can use the local .gdbinit file in your working directory.
Now you can make a separate .gdbinit for each project / directory and have them configured independently and not clutter up the global .gdbinit.

Visual Studio Code Task is Prepending the working directory to the command

I'm trying to setup visual studio code for rust to do debugging. In my launch.json file I have
{
"version": "0.2.0",
"configurations": [
{
"name": "(Windows) Launch",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceRoot}/target/debug/vscode-rust-debug-example.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": true,
"preLaunchTask": "localcargobuildtask"
}
]
}
and in my tasks.json I have
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "localcargobuildtask",
"command": "echo hi",
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
Where "echo hi" is in my tasks I eventually want to have something like "cargo build" or "cargo test" or whatever. But this is just a starting step.
But when I press F5 the output I get is
> Executing task: C:\programs\VSCodeWorkspaces\RustProjects\vscode-rust-debug-example-debug-config-included\echo hi <
The terminal process terminated with exit code: 2
Terminal will be reused by tasks, press any key to close it.
Rather than running "echo" from where ever the terminal finds it (working directory first, then check global path variable like you would expect) it is actually looking for a program named "echo" in my root folder of the workspace.
How do I tell visual studio code "No I don't want you to run workspace/echo, I want you to run echo in workspace" ? Or is there another more direct way to tell visual studio code "compile this before you debug it" ?
The answer to this question How to debug Rust unit tests on Windows?
suggests that changing
"command": "cargo build",
into
"command": "cargo",
"args": [
"build"
],
in the tasks.json file works and somehow it does. Maybe the editor is configured to search the %path% for single word commands, or maybe some plugin I installed overwrote the "cargo" command. Maybe the reason echo wasn't found is because it is a terminal command, not a program. Maybe the error message was a lie and it was only reporting that it couldn't find workspacefolder\command despite checking %path%? Or maybe none of that. I have no idea. It is some pretty idiosyncratic behavior.

Terminate another task from within a postDebugTask - VS Code

I have a debug launch configuration (launch.json) like below.
{
"version": "0.2.0",
"configurations": [
{
"name": "Current TS File",
"type": "node",
"request": "launch",
"preLaunchTask": "Pre Debug Task",
"postDebugTask": "Stop Watch Styles",
"args": ["${relativeFile}"],
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
"sourceMaps": true,
"cwd": "${workspaceRoot}",
"protocol": "inspector",
}
]
}
My tasks configuration (tasks.json) is like
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "next:copy",
"label": "Copy Files",
"problemMatcher": []
},
{
"type": "npm",
"script": "styles:tsw",
"label": "Watch Styles",
"problemMatcher": [],
},
{
"label": "Pre Debug Task",
"isBackground": true,
"dependsOn" :[
"Copy Files",
"Watch Styles"
]
},
{
"label": "Stop Watch Styles",
// No sure what should come here
}
]
}
Trying to stop watch process in postDebugTask, is there a way to Terminate Task by providing name (Watch Styles) as parameter in tasks.json. Watch styles is a continuously running process, please suggest if there is any other approach to terminate a task after debugging is complete.
This will terminate all tasks after debug stops
Or in this case, just build_runner watch...
launch.json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Flutter",
"request": "launch",
"type": "dart",
"flutterMode": "debug",
"preLaunchTask": "flutter: build_runner watch",
"postDebugTask": "Terminate All Tasks"
}
]
}
tasks.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Terminate All Tasks",
"command": "echo ${input:terminate}",
"type": "shell",
"problemMatcher": []
}
],
"inputs": [
{
"id": "terminate",
"type": "command",
"command": "workbench.action.tasks.terminate",
"args": "terminateAll"
}
]
}
More info here: https://code.visualstudio.com/docs/editor/variables-reference#_command-variables
This works for me:
{
"label": "postdebugKill",
"type": "process",
"command":[
"${command:workbench.action.tasks.terminate}",
"${command:workbench.action.acceptSelectedQuickOpenItem}",
],
},
The first "${command:workbench.action.tasks.terminate}" will bring up a panel asking you to select which task to terminate. So if you had multiple running tasks and wanted to choose one you would use this command only.
The second "${command:workbench.action.acceptSelectedQuickOpenItem}" will terminate the selected task in that panel mentioned above. (So you will not even see the terminate panel.) If you have only one running task when you call the postdebugKill task, it will be selected automatically and thus terminated. Otherwise whichever task is listed first will be terminated. Again, if you have more than one other task running and you want to select which to terminate don't include this second command.
I don't know of any way to list, perhaps via an args option a label name for which task to terminate if running. It would be nice to have this functionality.
[postdebugKill name can be whatever you want.]
To call a postdebug task your launch.json config might look like this:
{
"type": "node",
"request": "launch",
"name": "Gulp: serve",
"program": "${workspaceFolder}/node_modules/gulp/bin/gulp.js",
"args": [
"serve"
],
// "preLaunchTask": "someTask",
"postDebugTask": "postdebugKill"
},
Upon stopping that "Gulp: serve" debugging session, the task "postdebugKill" will be triggered. And so if I had used the "preLaunchTask" to start a task or had simply started a task running before launching the "Gulp: serve" debugging session - that preLaunchTask would be terminated.
The ability to run vscode commands in a task was recently added to vscode. Some minimal info here: using a command in a task doc.
[I'll add another answer because the new additional info is extensive.]
It seems there is an issue with running a preLaunchTask and then launching a debugging session. See particularly debugging does not work on first try. It appears to be fixed though in an insiders edition and may be released in early February 2019. terminal not sending onLineData.
In the meantime there is a suggested fix within one of the issues that I have lost the link to and that is a problemMatcher which will signal to the debugger that the dependent tasks have completed.
In my watching task I used this:
"problemMatcher": [
{
"base": "$tsc-watch",
"background": {
"activeOnStart": true,
"beginsPattern": "Using gulpfile ~\\OneDrive\\experimental\\gulpfile.js",
"endsPattern": "Starting 'watch'..."
}
}
],
I chose that because when I manually start the gulp:watch task I get this in the terminal:
[22:27:48] Using gulpfile ~\OneDrive\experimental\gulpfile.js
[22:27:48] Starting 'watch'...
[22:27:48] Starting 'watch'...
So you see the start and end pattern there that I copied (with extra escaping).
I suggest that you separately run your "Pre Debug Task" and copy the start and ending output into your "Pre Debug Task" problemMatcher and see if it now works.
My code in the first answer I believe is correct, I just wasn't using "isBackground" and "dependsOn" as you are. But I have added "isBackground" to mine and the problemMatcher option and it works flawlessly now.
Hopefully, this will be fixed in the next February 2019 release and there will be no need for this workaround.
If on Linux or macOS, a less hacky solution that just works is using pkill. If on Windows, see below.
First run the task and find the full command vscode runs for that task, with $ ps -af
Then use pkill + the full command in a postDebugTask.
I have an entry in tasks.json like this:
{
"label": "stop npm:watch",
"type": "shell",
"command": "pkill -f 'sh -c node ./scripts/watch.js'",
"presentation": {
"reveal": "silent",
"panel": "dedicated",
"close": true,
}
}
'sh -c node ./scripts/watch.js' is how vscode runs my npm:watch task.
The presentation properties prevent this task from taking focus or taking up terminal space after it finishes successfully.
Then you reference that task in a launch.json configuration:
{
...
"preLaunchTask": "npm:watch",
"postDebugTask": "stop npm:watch",
...
}
If the full command contains changing parameters (paths, port numbers, etc.), you can use a part of the command or regex.
e.g.: I could have probably matched with './scripts/watch.js' or 'node.*watch'.
For Windows: you can make this work by substituting pkill for taskkill.
If you want to support both Unix and Windows, you can make a script that does one or the other depending on the underlying OS.

Categories