)]}'
{
  "commit": "7fb620a5cc02a511a019d6918b0993b4cbdea825",
  "tree": "cf9c70f78922527f180a837e6d4d024cfc996b2d",
  "parents": [
    "cd834449a6d551cace6afad798ffad318f4ff325"
  ],
  "author": {
    "name": "qxy11",
    "email": "qxy11@meta.com",
    "time": "Mon Aug 04 08:43:49 2025 -0700"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Mon Aug 04 08:43:49 2025 -0700"
  },
  "message": "Fix a deadlock in ModuleList when starting a standalone lldb client/server (#148774)\n\nSummary:\nThere was a deadlock was introduced by [PR\n#146441](https://github.com/llvm/llvm-project/pull/146441) which changed\n`CurrentThreadIsPrivateStateThread()` to\n`CurrentThreadPosesAsPrivateStateThread()`. This change caused the\nexecution path in\n[`ExecutionContextRef::SetTargetPtr()`](https://github.com/llvm/llvm-project/blob/10b5558b61baab59c7d3dff37ffdf0861c0cc67a/lldb/source/Target/ExecutionContext.cpp#L513)\nto now enter a code block that was previously skipped, triggering\n[`GetSelectedFrame()`](https://github.com/llvm/llvm-project/blob/10b5558b61baab59c7d3dff37ffdf0861c0cc67a/lldb/source/Target/ExecutionContext.cpp#L522)\nwhich leads to a deadlock.\n\nThread 1 gets m_modules_mutex in\n[`ModuleList::AppendImpl`](https://github.com/llvm/llvm-project/blob/96148f92146e5211685246722664e51ec730e7ba/lldb/source/Core/ModuleList.cpp#L218),\nThread 3 gets m_language_runtimes_mutex in\n[`GetLanguageRuntime`](https://github.com/llvm/llvm-project/blob/96148f92146e5211685246722664e51ec730e7ba/lldb/source/Target/Process.cpp#L1501),\nbut then Thread 1 waits for m_language_runtimes_mutex in\n[`GetLanguageRuntime`](https://github.com/llvm/llvm-project/blob/96148f92146e5211685246722664e51ec730e7ba/lldb/source/Target/Process.cpp#L1501)\nwhile Thread 3 waits for m_modules_mutex in\n[`ScanForGNUstepObjCLibraryCandidate`](https://github.com/llvm/llvm-project/blob/96148f92146e5211685246722664e51ec730e7ba/lldb/source/Plugins/LanguageRuntime/ObjC/GNUstepObjCRuntime/GNUstepObjCRuntime.cpp#L57).\n\nThis fixes the deadlock by adding a scoped block around the mutex lock\nbefore the call to the notifier, and moved the notifier call outside of\nthe mutex-guarded section. The notifier call\n[`NotifyModuleAdded`](https://github.com/llvm/llvm-project/blob/96148f92146e5211685246722664e51ec730e7ba/lldb/source/Target/Target.cpp#L1810)\nshould be thread-safe, since the module should be added to the\n`ModuleList` before the mutex is released, and the notifier doesn\u0027t\nmodify the module list further, and the call is operates on local state\nand the `Target` instance.\n\n### Deadlocked Thread backtraces:\n```\n* thread #3, name \u003d \u0027dbg.evt-handler\u0027, stop reason \u003d signal SIGSTOP\n  * frame #0: 0x00007f2f1e2973dc libc.so.6`futex_wait(private\u003d0, expected\u003d2, futex_word\u003d0x0000563786bd5f40) at    futex-internal.h:146:13\n   /*... a bunch of mutex related bt ... */    \n   liblldb.so.21.0git`std::lock_guard\u003cstd::recursive_mutex\u003e::lock_guard(this\u003d0x00007f2f0f1927b0, __m\u003d0x0000563786bd5f40) at std_mutex.h:229:19\n    frame #8: 0x00007f2f27946eb7 liblldb.so.21.0git`ScanForGNUstepObjCLibraryCandidate(modules\u003d0x0000563786bd5f28, TT\u003d0x0000563786bd5eb8) at GNUstepObjCRuntime.cpp:60:41\n    frame #9: 0x00007f2f27946c80 liblldb.so.21.0git`lldb_private::GNUstepObjCRuntime::CreateInstance(process\u003d0x0000563785e1d360, language\u003deLanguageTypeObjC) at GNUstepObjCRuntime.cpp:87:8\n    frame #10: 0x00007f2f2746fca5 liblldb.so.21.0git`lldb_private::LanguageRuntime::FindPlugin(process\u003d0x0000563785e1d360, language\u003deLanguageTypeObjC) at LanguageRuntime.cpp:210:36\n    frame #11: 0x00007f2f2742c9e3 liblldb.so.21.0git`lldb_private::Process::GetLanguageRuntime(this\u003d0x0000563785e1d360, language\u003deLanguageTypeObjC) at Process.cpp:1516:9\n    ...\n    frame #21: 0x00007f2f2750b5cc liblldb.so.21.0git`lldb_private::Thread::GetSelectedFrame(this\u003d0x0000563785e064d0, select_most_relevant\u003dDoNoSelectMostRelevantFrame) at Thread.cpp:274:48\n    frame #22: 0x00007f2f273f9957 liblldb.so.21.0git`lldb_private::ExecutionContextRef::SetTargetPtr(this\u003d0x00007f2f0f193778, target\u003d0x0000563786bd5be0, adopt_selected\u003dtrue) at ExecutionContext.cpp:525:32\n    frame #23: 0x00007f2f273f9714 liblldb.so.21.0git`lldb_private::ExecutionContextRef::ExecutionContextRef(this\u003d0x00007f2f0f193778, target\u003d0x0000563786bd5be0, adopt_selected\u003dtrue) at ExecutionContext.cpp:413:3\n    frame #24: 0x00007f2f270e80af liblldb.so.21.0git`lldb_private::Debugger::GetSelectedExecutionContext(this\u003d0x0000563785d83bc0) at Debugger.cpp:1225:23\n    frame #25: 0x00007f2f271bb7fd liblldb.so.21.0git`lldb_private::Statusline::Redraw(this\u003d0x0000563785d83f30, update\u003dtrue) at Statusline.cpp:136:41\n    ...\n* thread #1, name \u003d \u0027lldb\u0027, stop reason \u003d signal SIGSTOP\n  * frame #0: 0x00007f2f1e2973dc libc.so.6`futex_wait(private\u003d0, expected\u003d2, futex_word\u003d0x0000563785e1dd98) at futex-internal.h:146:13\n   /*... a bunch of mutex related bt ... */    \n   liblldb.so.21.0git`std::lock_guard\u003cstd::recursive_mutex\u003e::lock_guard(this\u003d0x00007ffe62be0488, __m\u003d0x0000563785e1dd98) at std_mutex.h:229:19\n    frame #8: 0x00007f2f2742c8d1 liblldb.so.21.0git`lldb_private::Process::GetLanguageRuntime(this\u003d0x0000563785e1d360, language\u003deLanguageTypeC_plus_plus) at Process.cpp:1510:41\n    frame #9: 0x00007f2f2743c46f liblldb.so.21.0git`lldb_private::Process::ModulesDidLoad(this\u003d0x0000563785e1d360, module_list\u003d0x00007ffe62be06a0) at Process.cpp:6082:36\n    ...\n    frame #13: 0x00007f2f2715cf03 liblldb.so.21.0git`lldb_private::ModuleList::AppendImpl(this\u003d0x0000563786bd5f28, module_sp\u003dptr \u003d 0x563785cec560, use_notifier\u003dtrue) at ModuleList.cpp:246:19\n    frame #14: 0x00007f2f2715cf4c liblldb.so.21.0git`lldb_private::ModuleList::Append(this\u003d0x0000563786bd5f28, module_sp\u003dptr \u003d 0x563785cec560, notify\u003dtrue) at ModuleList.cpp:251:3\n    ...\n    frame #19: 0x00007f2f274349b3 liblldb.so.21.0git`lldb_private::Process::ConnectRemote(this\u003d0x0000563785e1d360, remote_url\u003d(Data \u003d \"connect://localhost:1234\", Length \u003d 24)) at Process.cpp:3250:9\n    frame #20: 0x00007f2f27411e0e liblldb.so.21.0git`lldb_private::Platform::DoConnectProcess(this\u003d0x0000563785c59990, connect_url\u003d(Data \u003d \"connect://localhost:1234\", Length \u003d 24), plugin_name\u003d(Data \u003d \"gdb-remote\", Length \u003d 10), debugger\u003d0x0000563785d83bc0, stream\u003d0x00007ffe62be3128, target\u003d0x0000563786bd5be0, error\u003d0x00007ffe62be1ca0) at Platform.cpp:1926:23\n```\n\n## Test Plan:\nBuilt a hello world a.out\nRun server in one terminal:\n```\n~/llvm/build/Debug/bin/lldb-server g :1234 a.out\n```\nRun client in another terminal\n```\n~/llvm/build/Debug/bin/lldb -o \"gdb-remote 1234\" -o \"b hello.cc:3\"\n```\n\nBefore:\nClient hangs indefinitely\n```\n~/llvm/build/Debug/bin/lldb -o \"gdb-remote 1234\" -o \"b main\"\n(lldb) gdb-remote 1234\n\n^C^C\n```\n\nAfter:\n```\n~/llvm/build/Debug/bin/lldb -o \"gdb-remote 1234\" -o \"b hello.cc:3\"\n(lldb) gdb-remote 1234\nProcess 837068 stopped\n* thread #1, name \u003d \u0027a.out\u0027, stop reason \u003d signal SIGSTOP\n    frame #0: 0x00007ffff7fe4a60\nld-linux-x86-64.so.2`_start:\n-\u003e  0x7ffff7fe4a60 \u003c+0\u003e: movq   %rsp, %rdi\n    0x7ffff7fe4a63 \u003c+3\u003e: callq  0x7ffff7fe5780 ; _dl_start at rtld.c:522:1\n\nld-linux-x86-64.so.2`_dl_start_user:\n    0x7ffff7fe4a68 \u003c+0\u003e: movq   %rax, %r12\n    0x7ffff7fe4a6b \u003c+3\u003e: movl   0x18067(%rip), %eax ; _dl_skip_args\n(lldb) b hello.cc:3\nBreakpoint 1: where \u003d a.out`main + 15 at hello.cc:4:13, address \u003d 0x00005555555551bf\n(lldb) c\nProcess 837068 resuming\nProcess 837068 stopped\n* thread #1, name \u003d \u0027a.out\u0027, stop reason \u003d breakpoint 1.1\n    frame #0: 0x00005555555551bf a.out`main at hello.cc:4:13\n   1   \t#include \u003ciostream\u003e\n   2\n   3   \tint main() {\n-\u003e 4   \t  std::cout \u003c\u003c \"Hello World\" \u003c\u003c std::endl;\n   5   \t  return 0;\n   6   \t}\n```",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "01f46b62b57bddd33573b531e407ca9af72e07ea",
      "old_mode": 33188,
      "old_path": "lldb/source/Core/ModuleList.cpp",
      "new_id": "d5ddc2b249e56ebbc25ea701e65a46a31a7876fe",
      "new_mode": 33188,
      "new_path": "lldb/source/Core/ModuleList.cpp"
    },
    {
      "type": "modify",
      "old_id": "087e62b387d77ee2e48da910d9394f6b19499f68",
      "old_mode": 33188,
      "old_path": "lldb/test/API/functionalities/statusline/TestStatusline.py",
      "new_id": "33cd79736dc3816db47f8ccd5e9e011762269187",
      "new_mode": 33188,
      "new_path": "lldb/test/API/functionalities/statusline/TestStatusline.py"
    }
  ]
}
