Skip to content

lldb-mi freezes on MacOS when breaking near uninitialised variables #7240

@andrewfindon

Description

@andrewfindon

Type: Debugger

Describe the bug

  • OS and Version: MacOS 11.2.3 (Big Sur)
  • VS Code Version: 1.5.4.3
  • C/C++ Extension Version: 1.2.2
  • I have recreated on both Intel and Apple Silicon (Rosetta) MacBook Pros.

During debugging, if stopping on (or stepping in to) a frame containing certain types of uninitialised variables, lldb-mi gets stuck at 100% cpu and starts to consume multiple GBs of memory.

I've encountered this a a few times in different code, I've condensed the latest example in to a tiny snippet (below), using a std::initialiser_list<int>.

I couldn't reproduce using the lldb command line. Xcode is fine too, but I notice it uses lldb-rpc-server to communicate with debugserver instead of lldb-mi.

I also tried using the CodeLLDB extension (https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) which doesn't suffer with the same problem (and doesn't use lldb-mi) - but interestingly, it does try to inspect the values of the initializer_list but times out after a short time.

If debugging is stopped while this is going on, the lldb-mi process continue to spin with high cpu usage in the background.

This may be related to the following:

The issue may not be directly related to cpptools (could be an lldb-mi bug?), but the extension suffers as a result - in that case, maybe there is something between the interaction with lldb-mi and cpptools that could avoid triggering the bug.

To Reproduce

(I've also prepared a tiny repo for easily reproducing the problem here: https://github.com/andrewfindon/lldbmi-freeze)

To trigger the problem, step in to the freeze_up() function in the example below. The lldb-mi process should spike in cpu/memory usage and vscode will appear to freeze waiting for local variables to resolve.

main.cpp

#include <initializer_list>

void freeze_up()
{
	auto bad_var = {1, 2, 3};		// A breakpoint here will trigger the issue.
}						// A breakpoint here is fine (bad_var is initialised).

int main() {
	freeze_up();
	
	return 0;
}

launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/freeze",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "lldb",
            "preLaunchTask": "clang++ build",

            "logging": {
                "engineLogging": true,
                "trace": true,
                "traceResponse": true
            }
        }
    ]
}

tasks.json

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "clang++ build",
            "command": "/usr/bin/clang++",
            "args": [
                "main.cpp",
                "-arch",
                "x86_64",
                "-std=c++17",
                "-Wall",
                "-g",
                "-o",
                "freeze",
            ],
            "problemMatcher": [
                "$gcc"
            ],
            "group": "build",
        }
    ]
}

The tail of my engine logging output at the point where the debugger has frozen on a breakpoint, looks like:

--> E (stopped): {"type":"event","event":"stopped","body":{"reason":"step","threadId":1,"allThreadsStopped":true,"source":{"name":"main.cpp","path":"/Users/andrewfindon/Documents/lldbmi-crash/main.cpp","sources":[],"checksums":[]},"line":6,"column":1},"seq":641}
<--   C (threads-12): {"command":"threads","type":"request","seq":12}
--> R (threads-12): {"type":"response","request_seq":12,"success":true,"command":"threads","body":{"threads":[{"id":1,"name":"Thread #1"}]},"seq":644}
<--   C (stackTrace-13): {"command":"stackTrace","arguments":{"threadId":1,"startFrame":0,"levels":20},"type":"request","seq":13}
--> R (stackTrace-13): {"type":"response","request_seq":13,"success":true,"command":"stackTrace","body":{"stackFrames":[{"id":1000,"name":"freeze!freeze_up()","source":{"name":"main.cpp","path":"/Users/andrewfindon/Documents/lldbmi-crash/main.cpp","sources":[],"checksums":[]},"line":6,"column":1,"moduleId":1},{"id":1001,"name":"freeze!main","source":{"name":"main.cpp","path":"/Users/andrewfindon/Documents/lldbmi-crash/main.cpp","sources":[],"checksums":[]},"line":12,"column":1,"moduleId":1},{"id":1002,"name":"libdyld.dylib!start","line":0,"column":0,"moduleId":12},{"id":1003,"name":"libdyld.dylib!start","line":0,"column":0,"moduleId":12}],"totalFrames":4},"seq":647}
<--   C (scopes-14): {"command":"scopes","arguments":{"frameId":1000},"type":"request","seq":14}
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (33618) <-1018-stack-list-variables 0 --thread 1 --frame 0\n"},"seq":650}
1: (33618) <-1018-stack-list-variables 0 --thread 1 --frame 0
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (33631) ->1018^done,variables=[{name=\"bad_var\"}]\n"},"seq":652}
1: (33631) ->1018^done,variables=[{name="bad_var"}]
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (33631) ->(gdb)\n"},"seq":654}
1: (33631) ->(gdb)
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (33632) 1018: elapsed time 13\n"},"seq":656}
1: (33632) 1018: elapsed time 13
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (33657) <-1019-var-create - - \"bad_var\" --thread 1 --frame 0\n"},"seq":658}
1: (33657) <-1019-var-create - - "bad_var" --thread 1 --frame 0

Here's a trace of lldb-mi in Instruments - it's clear on the timeline when I stepped in to the freeze_up function:
image

Example debugging session:

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugdebuggerhelp wantedCan be fixed in the public (open source) repo.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions