microsoft / microsoft/vscode-cpptools

Watch Chromium Nodes Hangs Debugger, gdb.txt Grows w/o Bound

Open
#8,257 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

debugger
Dominant language
TypeScript
Stars
6.2k
Forks
1.7k
Avg merge
14h 46m
Merged PRs (30d)
61

Description

Bug type: Debugger

Describe the bug

I'm building and debugging Chromium on Linux with gdb.

I can set breakpoints, step, and do simple evaluations. But periodically the debugger would hang infinitely, and become unresponsive...with the only option being to terminate the debug process and start it again. It is related to watching node variables (which can happen on hovering, making it seem more random, since there's no feedback to make an obvious connection with the next time you make a request).

I figured out it was Blink::Node templates by asking to expand a document in the Variables panel at a certain breakpoint. It would get a spinning circle and never return. (FWIW, the document is nothing complicated--it is one paragraph with the letters "Ab" in it, though even minimal documents do carry a fair amount of data.)

I tried to investigate this myself by building vscode and the vscode-cpptools. But that dead-ended at $sendDAMessage in extHostDebugService.ts, where this request is made:

message: {
    args: {variablesReference: 1003}
    command: 'variables'
    seq: 64
    type: 'request'
}

But no answer comes back. :-(

So I did set logging on in GDB to see what it was getting asked. And while the debugger is hanging, the gdb.txt file is just growing and growing into a hundreds of megabyte file (500MB before I stopped it) with lines that start with this, and thereafter all look like this:

5114^done,numchild="1",children=[child={name="var1703.blink::ContainerNode.blink::Node.blink::EventTarget.private.wrapper_type_info_",exp="wrapper_type_info_",numchild="1",value="{...}",type="const blink::WrapperTypeInfo &",thread-id="35"}],has_more="0"
(gdb) 
5115^done,numchild="3",children=[child={name="var1703.blink::ContainerNode.blink::Node.blink::EventTarget.blink::ScriptWrappable.blink::GarbageCollected<blink::ScriptWrappable>",exp="blink::GarbageCollected<blink::ScriptWrappable>",numchild="3",type="blink::ScriptWrappable",thread-id="35"},child={name="var1703.blink::ContainerNode.blink::Node.blink::EventTarget.blink::ScriptWrappable.blink::NameClient",exp="blink::NameClient",numchild="1",type="blink::NameClient",thread-id="35"},child={name="var1703.blink::ContainerNode.blink::Node.blink::EventTarget.blink::ScriptWrappable.private",exp="private",numchild="1",value="",thread-id="35"}],has_more="0"
(gdb) 
5116^done,numchild="1",children=[child={name="var1703.blink::ContainerNode.blink::Node.blink::EventTarget.blink::ScriptWrappable.private.main_world_wrapper_",exp="main_world_wrapper_",numchild="1",type="blink::TraceWrapperV8Reference<v8::Object>",thread-id="35"}],has_more="0"
(gdb) 
5117^done,numchild="3",children=[child={name="var1703.blink::ContainerNode.blink::Node.blink::EventTarget.blink::ScriptWrappable.blink::GarbageCollected<blink::ScriptWrappable>.blink::GarbageCollected<blink::ScriptWrappable>",exp="blink::GarbageCollected<blink::ScriptWrappable>",numchild="3",type="blink::ScriptWrappable",thread-id="35"},child={name="var1703.blink::ContainerNode.blink::Node.blink::EventTarget.blink::ScriptWrappable.blink::GarbageCollected<blink::ScriptWrappable>.blink::NameClient",exp="blink::NameClient",numchild="1",type="blink::NameClient",thread-id="35"},child={name="var1703.blink::ContainerNode.blink::Node.blink::EventTarget.blink::ScriptWrappable.blink::GarbageCollected<blink::ScriptWrappable>.private",exp="private",numchild="1",value="",thread-id="35"}],has_more="0"
(gdb) 
5118^done,numchild="1",children=[child={name="var1703.blink::ContainerNode.blink::Node.blink::EventTarget.blink::ScriptWrappable.blink::GarbageCollected<blink::ScriptWrappable>.private.main_world_wrapper_",exp="main_world_wrapper_",numchild="1",type="blink::TraceWrapperV8Reference<v8::Object>",thread-id="35"}],has_more="0"

That pattern repeats indefinitely--at least it would appear so. (I'd let it run for a much longer time without the gdb log, and it still didn't terminate.)

In the debug console if I say -exec print document I get a sizable output...many pages of information from a GDB print:

$1 = (const blink::HTMLDocument &) @0x13300828980: {
  <blink::Document> = {
    <blink::ContainerNode> = {
      <blink::Node> = {
        <blink::EventTarget> = {
          <blink::ScriptWrappable> = {
               ...

But it's on the order of pages of information, not not 500MB+. So it seems like the vscode-provoked output in the watch is caught in some kind of cycle, related to following the pointers in the templates that support making an object part of the GC (?)

To Reproduce

  • Build Chromium according to the directions.
    • Do not take their suggestion of speeding up the build with blink_symbol_level=0
      • Blink is the renderer, and debug watching Blink::Node is what's at issue.
  • Configure debugging for Linux
    • This involves adding their tools/gdb/gdbinit to ~/.gdbinit
      • Debugging requires the directory configuration from this file
      • The pretty printer does not seem to be involved with the problem, as the debugger isn't using it.
        • For good measure I commented out load_libcxx_pretty_printers() and load_gdb_chrome() from that gdbinit but it did not affect the issue
  • Use the attached launch.json to start a debug session
    • On my machine this forces one debug break to notify you of a certificate alert
      • Just continue the debugger when it happens
    • To pick an example: set a breakpoint in this painting code, line 294 at time of writing
    • Hover over the node assigned in line 293 when the breakpoint hits
    • Once you have done so, stepping should no longer work; out/Default/gdb.txt should be growing without bound
      • Problem happens on any Blink::Node variable, or a variable that contains one, like document
      • Will occur on hovering or expansion in a Watch or Variables pane

I'll note that the Chromium docs mention that the Blink templates are pretty gnarly. Be that as it may, it's impractical to avoid hovering over things, and the debugger does not heed "editor.hover.enabled": false. (Actually, it seems restarting makes it pay attention to the hover change...? Still, disabling all hovering in the system is a heavy-handed workaround, and having to use gdb in the debug console to do all variable inspections is suboptimal. Slightly less painful by using backtick instead of -exec, for anyone reading this who does not know about that.)

// launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/../out/Default/chrome",
            "args": [
                "--no-sandbox",
                "--disable-seccomp-sandbox",
                "--single-process",
                "--disable-gpu",
                "--disable-hang-monitor"
            ],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {"text": "set logging on"}  // to see gdb.txt grow (seemingly) without bound
            ],
            "logging": {"trace": true}
        }
    ]
}

P.S. Originally I built Chromium in Ubuntu 18 because that's what it said the directions were for. When this debug hanging issue arose, I upgraded to Ubuntu 20 to see if it would change anything (gdb 9.2). I then tried debugging with a gdb 11 that I built from source (which also did not help). Then before going into debugging gdb itself I found the option to log what commands it was getting to a file, which is when I found that the debug adapter was sending it seemingly infinite requests.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at src/vs/workbench/api/common/extHostDebugService.ts around the $sendDAMessage variables request, then reproduce with the supplied launch.json and Chromium Blink::Node hover or expansion steps. Use the gdb.txt logging described in the report to trace the repeated variables requests; done means inspecting a Blink::Node no longer hangs the debugger or grows the log without bound.

Written by the indexing model from the issue text.

Assessment

Domain
devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.