microsoft / microsoft/vscode-cpptools
Very long delay when a breakpoint is hit and many (150+) threads are created by the program
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 6.2k
- Forks
- 1.7k
- Avg merge
- 14h 46m
- Merged PRs (30d)
- 61
Description
Environment
- OS and version: Ubuntu 20.04.5 LTS
- VS Code: 1.72.1
- C/C++ extension: v1.12.4
- OS and version of remote machine (if applicable): gdbserver is running on an embedded ARMv7 Linux
- GDB version: 7.4
Bug Summary and Steps to Reproduce
Bug Summary:
I am developing a C application with 150+ threads and debug it remotely via gdbserver. When the first breakpoint is hit, vscode requests detailed information about every thread in the application and it takes about 3 minutes to complete. The debugging is very painful due to this.
The communication between gdb and gdbserver is very sensitive to the network latency. It is important to make as few requests to gdb/gdbserver as possible.
Steps to reproduce:
Create an app which starts 150+ threads.
Debug it remotely using gdbserver.
Set a breakpoint to be hit after all threads are created already.
Debug the program.
When the breakpoint is hit you will get a significant delay before vscode UI reports the breakpoint hit.
Debugger Configurations
{
// 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": "(gdb) Debug app",
"type": "cppdbg",
"request": "launch",
"program": "link.out",
"stopAtEntry": false,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
"miDebuggerPath": "arm-linux-gnueabi-gdb",
"miDebuggerServerAddress": "10.0.1.10:9099",
"targetArchitecture": "arm",
"symbolLoadInfo": {
"loadAll": false
},
"logging": {
"engineLogging": false
},
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"text": "-interpreter-exec console \"set sysroot build_dir/sysroot\"",
"ignoreFailures": true
}
]
}
]
}
Debugger Logs
Here is what happens when a break point is hit and why it takes so long.
The break point is hit:
1: (20384) ->=thread-created,id="2",group-id="i1"
1: (20384) ->~"[New Thread 1800]\n"
1: (20385) <-1023-thread-info 2
[New Thread 1800]
1: (20389) ->=breakpoint-modified,bkpt={number="3",type="breakpoint",disp="keep",enabled="y",addr="0x00b5efb4",func="x",file="x.c",fullname="x.c",line="568",times="1",original-location="x.c:568"}
1: (20390) ->~"[Switching to Thread 1800]\n"
[Switching to Thread 1800]
1: (20466) ->*stopped,reason="breakpoint-hit",disp="keep",bkptno="3",frame={addr="0x00b5efb4",func="x",args=[],file="x.c",fullname="x.c",line="568"},thread-id="2",stopped-threads="all",core="0"
Information about all(!) threads is requested:
1: (20467) <-1024-thread-info
While GDB executes the request above, it reports availability of new threads (158 in my case):
1: (20509) ->=thread-created,id="3",group-id="i1"
1: (20509) ->~"[New Thread 1639]\n"
1: (20509) ->=thread-created,id="4",group-id="i1"
1: (20509) ->~"[New Thread 1640]\n"
1: (20509) ->=thread-created,id="5",group-id="i1"
1: (20510) ->~"[New Thread 1641]\n"
vscode starts to request info about each reported thread. Even though information about all threads has been requested earlier:
1: (20510) <-1025-thread-info 3
1: (20510) ->=thread-created,id="6",group-id="i1"
1: (20510) ->~"[New Thread 1642]\n"
[New Thread 1639]
1: (20510) ->=thread-created,id="7",group-id="i1"
1: (20510) ->~"[New Thread 1649]\n"
1: (20510) ->=thread-created,id="8",group-id="i1"
...
...
1: (20528) <-1178-thread-info 156
[New Thread 1798]
1: (20528) <-1179-thread-info 157
[New Thread 1799]
1: (20528) <-1180-thread-info 158
[New Thread 1801]
1: (20528) 1023: elapsed time 143
1: (20528) Send Event AD7ThreadCreateEvent
...
Information about all 158 threads has been requested.
After 11 seconds GDB returns response to request -thread-info``` and starts to slowly return responses for individual thread info requests:
...
1: (31603) ->1024^done,threads=[{id="158",target-id="Thread 1801",frame={level="0",addr="0xb6e97798",func="??",args=[]},state="stopped",core="0"},{id="157",target-id="Thread 1799",frame={level="0",addr="0xb6fa7ce4",func="??",args=[]},state="stopped",core="0"}, ...
1: (31604) ->(gdb)
1: (31606) 1024: elapsed time 11138
1: (32457) ->1025^done,threads=[{id="3",target-id="Thread 1639",frame={level="0",addr="0xb6e91e7c",func="??",args=[]},state="stopped",core="0"}]
1: (32458) ->(gdb)
1: (32458) 1025: elapsed time 11948
1: (33343) ->1026^done,threads=[{id="4",target-id="Thread 1640",frame={level="0",addr="0xb6e97798",func="??",args=[]},state="stopped",core="0"}]
...
After 151 (!) seconds GDB responds to the last thread info request and vscode is almost ready to inform a user about the break point:
...
1: (171843) ->1180^done,threads=[{id="158",target-id="Thread 1801",frame={level="0",addr="0xb6e97798",func="??",args=[]},state="stopped",core="0"}]
1: (171843) ->(gdb)
1: (171844) 1180: elapsed time 151315
1: (171845) <-1181-stack-list-frames 0 1000
Conclusion: it is not needed to request individual thread info since all thread info is requested anyway and such combined request is executed much much faster compared to many individual requests.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing handling of the -thread-info request and thread-created events in the TypeScript extension, using the supplied debugger logs as the behavioral reference. Reproduce with an application creating 150+ threads over remote gdbserver, then verify that hitting a breakpoint does not issue redundant per-thread requests and that the breakpoint becomes visible without the reported delay.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, typescript
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100