| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -438,6 +438,56 @@ def _extract_coroutine_stacks_lineno_only(self, stack_trace): | |||
| 438 | 438 | # ============================================================================ | |
| 439 | 439 | ||
| 440 | 440 | ||
| 441 | + @requires_remote_subprocess_debugging() | ||
| 442 | + class TestSelfStackTrace(RemoteInspectionTestBase): | ||
| 443 | + @skip_if_not_supported | ||
| 444 | + @unittest.skipIf( | ||
| 445 | + sys.platform == "linux" and not PROCESS_VM_READV_SUPPORTED, | ||
| 446 | + "Test only runs on Linux with process_vm_readv support", | ||
| 447 | + ) | ||
| 448 | + def test_self_trace_with_large_linetable(self): | ||
| 449 | + script = textwrap.dedent("""\ | ||
| 450 | + import os | ||
| 451 | + import _remote_debugging | ||
| 452 | + | ||
| 453 | + assignments = "\\n".join( | ||
| 454 | + f"value_{i} = {i}" for i in range(1000) | ||
| 455 | + ) | ||
| 456 | + expected_lineno = len(assignments.splitlines()) + 1 | ||
| 457 | + source = ( | ||
| 458 | + f"{assignments}\\n" | ||
| 459 | + "stack_trace = " | ||
| 460 | + "_remote_debugging.RemoteUnwinder(os.getpid()).get_stack_trace()\\n" | ||
| 461 | + ) | ||
| 462 | + code = compile(source, "large_linetable.py", "exec") | ||
| 463 | + assert len(code.co_linetable) > 4096, len(code.co_linetable) | ||
| 464 | + namespace = {"os": os, "_remote_debugging": _remote_debugging} | ||
| 465 | + exec(code, namespace) | ||
| 466 | + large_linetable_frames = [ | ||
| 467 | + frame | ||
| 468 | + for interpreter in namespace["stack_trace"] | ||
| 469 | + for thread in interpreter.threads | ||
| 470 | + for frame in thread.frame_info | ||
| 471 | + if frame.filename == "large_linetable.py" | ||
| 472 | + ] | ||
| 473 | + assert len(large_linetable_frames) == 1, large_linetable_frames | ||
| 474 | + assert large_linetable_frames[0].location.lineno == expected_lineno, ( | ||
| 475 | + large_linetable_frames[0] | ||
| 476 | + ) | ||
| 477 | + """) | ||
| 478 | + | ||
| 479 | + result = subprocess.run( | ||
| 480 | + [sys.executable, "-c", script], | ||
| 481 | + capture_output=True, | ||
| 482 | + text=True, | ||
| 483 | + timeout=SHORT_TIMEOUT, | ||
| 484 | + ) | ||
| 485 | + self.assertEqual( | ||
| 486 | + result.returncode, 0, | ||
| 487 | + f"stdout: {result.stdout}\nstderr: {result.stderr}" | ||
| 488 | + ) | ||
| 489 | + | ||
| 490 | + | ||
| 441 | 491 | @requires_remote_subprocess_debugging() | |
| 442 | 492 | class TestGetStackTrace(RemoteInspectionTestBase): | |
| 443 | 493 | @skip_if_not_supported | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,2 @@ | |||
| 1 | + Fix ``_remote_debugging`` stack traces for code objects with large line | ||
| 2 | + tables. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,6 +7,8 @@ | |||
| 7 | 7 | ||
| 8 | 8 | #include "_remote_debugging.h" | |
| 9 | 9 | ||
| 10 | + #define MAX_LINETABLE_SIZE (64 * 1024) | ||
| 11 | + | ||
| 10 | 12 | /* ============================================================================ | |
| 11 | 13 | * TLBC CACHING FUNCTIONS (Py_GIL_DISABLED only) | |
| 12 | 14 | * ============================================================================ */ | |
@@ -186,11 +188,7 @@ parse_linetable(const uintptr_t addrq, const char* linetable, Py_ssize_t linetab | |||
| 186 | 188 | int computed_line = firstlineno; // Running accumulator, separate from output | |
| 187 | 189 | int val; // Temporary for varint results | |
| 188 | 190 | uint8_t byte; // Temporary for byte reads | |
| 189 | - const size_t MAX_LINETABLE_ENTRIES = 65536; | ||
| 190 | - size_t entry_count = 0; | ||
| 191 | - | ||
| 192 | - while (ptr < end && *ptr != '\0' && entry_count < MAX_LINETABLE_ENTRIES) { | ||
| 193 | - entry_count++; | ||
| 191 | + while (ptr < end && *ptr != '\0') { | ||
| 194 | 192 | uint8_t first_byte = *(ptr++); | |
| 195 | 193 | uint8_t code = (first_byte >> 3) & 15; | |
| 196 | 194 | size_t length = (first_byte & 7) + 1; | |
@@ -387,7 +385,8 @@ parse_code_object(RemoteUnwinderObject *unwinder, | |||
| 387 | 385 | } | |
| 388 | 386 | ||
| 389 | 387 | linetable = read_py_bytes(unwinder, | |
| 390 | - GET_MEMBER(uintptr_t, code_object, unwinder->debug_offsets.code_object.linetable), 4096); | ||
| 388 | + GET_MEMBER(uintptr_t, code_object, unwinder->debug_offsets.code_object.linetable), | ||
| 389 | + MAX_LINETABLE_SIZE); | ||
| 391 | 390 | if (!linetable) { | |
| 392 | 391 | set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read linetable from code object"); | |
| 393 | 392 | goto error; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments