Dump stack trace using gdb.
(gdb_path: str, pid: int, test_name: str)
| 159 | |
| 160 | |
| 161 | def _dump_with_gdb(gdb_path: str, pid: int, test_name: str) -> Optional[str]: |
| 162 | """Dump stack trace using gdb.""" |
| 163 | # Create gdb command script |
| 164 | with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".gdb") as f: |
| 165 | f.write("set pagination off\n") |
| 166 | f.write("set confirm off\n") |
| 167 | f.write("set print pretty on\n") |
| 168 | f.write("\n") |
| 169 | f.write("# Get backtrace for all threads\n") |
| 170 | f.write("thread apply all backtrace full\n") |
| 171 | f.write("\n") |
| 172 | f.write("# Show thread info\n") |
| 173 | f.write("info threads\n") |
| 174 | f.write("\n") |
| 175 | f.write("quit\n") |
| 176 | script_path = f.name |
| 177 | |
| 178 | try: |
| 179 | # Run gdb with the script |
| 180 | cmd = [ |
| 181 | gdb_path, |
| 182 | "--batch", |
| 183 | "--command", |
| 184 | script_path, |
| 185 | "--pid", |
| 186 | str(pid), |
| 187 | ] |
| 188 | |
| 189 | ts_print(f"Running: {' '.join(cmd)}") |
| 190 | |
| 191 | result = RunningProcess.run( |
| 192 | cmd, |
| 193 | cwd=None, |
| 194 | check=False, |
| 195 | timeout=30, # 30 second timeout for debugger |
| 196 | ) |
| 197 | |
| 198 | output = result.stdout |
| 199 | |
| 200 | # Clean up script |
| 201 | os.unlink(script_path) |
| 202 | |
| 203 | if output and output.strip(): |
| 204 | return output |
| 205 | else: |
| 206 | return "Debugger attached but produced no output" |
| 207 | |
| 208 | except RuntimeError as e: |
| 209 | if "timeout" in str(e).lower(): |
| 210 | ts_print("⏱️ Debugger timed out after 30 seconds") |
| 211 | else: |
| 212 | ts_print(f"Debugger error: {e}") |
| 213 | try: |
| 214 | os.unlink(script_path) |
| 215 | except KeyboardInterrupt as ki: |
| 216 | handle_keyboard_interrupt(ki) |
| 217 | except: |
| 218 | pass |
no test coverage detected