Attach lldb to a process and dump stack traces for all threads. NOTE: Crash handlers use signal chaining - they dump internally first, then uninstall themselves and re-raise signals. This allows both internal crash dumps (for actual crashes) and external debugger attachment (for ha
(pid: int, test_name: str)
| 38 | |
| 39 | |
| 40 | def dump_stack_trace_lldb(pid: int, test_name: str) -> Optional[str]: |
| 41 | """ |
| 42 | Attach lldb to a process and dump stack traces for all threads. |
| 43 | |
| 44 | NOTE: Crash handlers use signal chaining - they dump internally first, |
| 45 | then uninstall themselves and re-raise signals. This allows both internal |
| 46 | crash dumps (for actual crashes) and external debugger attachment (for hangs). |
| 47 | |
| 48 | The process can optionally set FASTLED_DISABLE_CRASH_HANDLER=1 to completely |
| 49 | disable internal handlers if only external dumps are desired. |
| 50 | |
| 51 | Args: |
| 52 | pid: Process ID to attach to |
| 53 | test_name: Name of the test (for logging) |
| 54 | |
| 55 | Returns: |
| 56 | Stack trace output or None if failed |
| 57 | """ |
| 58 | debugger, debugger_type = find_debugger() |
| 59 | |
| 60 | if not debugger or debugger_type == "none": |
| 61 | ts_print( |
| 62 | "⚠️ No debugger found (clang-tool-chain-lldb or gdb required for stack traces)" |
| 63 | ) |
| 64 | ts_print( |
| 65 | " LLDB is bundled with clang-tool-chain (already installed via pyproject.toml)" |
| 66 | ) |
| 67 | return None |
| 68 | |
| 69 | ts_print(f"📍 Attaching {debugger_type} to hung process (PID {pid})...") |
| 70 | ts_print( |
| 71 | " Note: Crash handlers use signal chaining (internal dump → external debugger)" |
| 72 | ) |
| 73 | |
| 74 | try: |
| 75 | if debugger_type == "lldb": |
| 76 | return _dump_with_lldb(debugger, pid, test_name) |
| 77 | else: # gdb |
| 78 | return _dump_with_gdb(debugger, pid, test_name) |
| 79 | except KeyboardInterrupt as ki: |
| 80 | handle_keyboard_interrupt(ki) |
| 81 | except Exception as e: |
| 82 | ts_print(f"❌ Failed to attach debugger: {e}") |
| 83 | return None |
| 84 | |
| 85 | |
| 86 | def _dump_with_lldb(lldb_path: str, pid: int, test_name: str) -> Optional[str]: |
no test coverage detected