@maurycy I could reproduce this on current main with the html.entities example. The line table is 37445 bytes, so the failure happens before parsing because the remote bytes read is capped at 4096.
I opened #151036 with a narrow fix. It keeps the generic remote bytes reader bounded, but uses a separate larger bound for code object line tables. I also added a regression test that builds a code object with a line table over 4096 bytes and verifies that same-process unwinding succeeds.
@pablogsal The more I think about this... For the purpose of mach_vm_remap, I'm trying to measure the bias (ie: delta between the truth and what we report, with aliasing and sampling rates between 2-5MHz I started to wonder about it; spoiler: we're great here.) But the original issue reports heavy bias actually... linetable, qualname/filename and MAX_FRAMES (and this _sync_coordinator.py; unlucky person who accidentially uses this name too) drop the whole frame silently. Now, for a long-running profiler on a large-scale production system a heavy bias, like the one observed originally, makes the profiling not trustworthy, and time completely wasted. In other words, apart from making the limits realistic, I believe we should not drop the frames on limit but degrade
@pablogsal The more I think about this... For the purpose of mach_vm_remap, I'm trying to measure the bias (ie: delta between the truth and what we report, with aliasing and sampling rates between 2-5MHz I started to wonder about it; spoiler: we're great here.) But the original issue reports heavy bias actually... linetable, qualname/filename and MAX_FRAMES (and this _sync_coordinator.py; unlucky person who accidentially uses this name too) drop the whole frame silently. Now, for a long-running profiler on a large-scale production system a heavy bias, like the one observed originally, makes the profiling not trustworthy, and time completely wasted. In other words, apart from making the limits realistic, I believe we should not drop the frames on limit but degrade
What kind of degradation did you have in mind? Emitting the frame with line unknown when the linetable read fails, or something more specific?
@pablogsal The more I think about this... For the purpose of mach_vm_remap, I'm trying to measure the bias (ie: delta between the truth and what we report, with aliasing and sampling rates between 2-5MHz I started to wonder about it; spoiler: we're great here.) But the original issue reports heavy bias actually... linetable, qualname/filename and MAX_FRAMES (and this _sync_coordinator.py; unlucky person who accidentially uses this name too) drop the whole frame silently. Now, for a long-running profiler on a large-scale production system a heavy bias, like the one observed originally, makes the profiling not trustworthy, and time completely wasted. In other words, apart from making the limits realistic, I believe we should not drop the frames on limit but degrade
What kind of degradation did you have in mind? Emitting the frame with line unknown when the linetable read fails, or something more specific?
Yes, only this, truncation or a placeholder in case of qualname/filename or MAX_FRAMES etc. I think. More than open for any other ideas.
python.exe -m profiling.sampling run pystone.py 100000
I also get a high error rate (about 30%) on Windows (if that makes a difference).
The attached PR doesn't help, and also from the errors I think this must be something different:
Lots of
Failed to parse initial frame in chain
ReadProcessMemory failed for PID 24180 at address 0xc0000000 (size 64, partial read 0 bytes): Windows error 998
ReadProcessMemory failed for PID 24180 at address 0xe7 (size 64, partial read 0 bytes): Windows error 299
Where ERROR_NOACCESS=998 and ERROR_PARTIAL_COPY=299, which all indicate reading from invalid memory (already quite obvious from the pointer values).
@chris-eibl Thanks for testing this on Windows. I updated the PR to use a 64 KiB line-table limit and removed the separate entry-count limit.
The ReadProcessMemory errors shown here occur while resolving the initial frame chain, before line-table parsing begins, so they appear to be a separate failure path from the large-line-table issue addressed by #151036.
Could you compare the same pystone run with --blocking? If the errors disappear, that would help determine whether the invalid frame addresses come from a race in the non-blocking snapshot path. I think the Windows frame-chain failure should otherwise be tracked separately so both problems remain independently reproducible. Let me know.
cc @maurycy
Yeah, --blocking drastically reduces the error rate (after applying #152471). And I agree this is a different (and most probably only Windows related) issue.
However, non-blocking sampling can occasionally produce incomplete or inconsistent stack traces [...] in programs with very fast-changing call stacks where functions enter and exit between the start and end of a single stack read
very much applies to pystone.py. I've just wondered about the high error rate without giving it a closer thought. Sorry for the noise here ...
Activity
maurycy commented on Jun 6, 2026
cc @pablogsal 2^16 is tempting :-)
pablogsal commented on Jun 6, 2026
goutamadwant commented on Jun 6, 2026
@maurycy I could reproduce this on current main with the html.entities example. The line table is 37445 bytes, so the failure happens before parsing because the remote bytes read is capped at 4096.
I opened #151036 with a narrow fix. It keeps the generic remote bytes reader bounded, but uses a separate larger bound for code object line tables. I also added a regression test that builds a code object with a line table over 4096 bytes and verifies that same-process unwinding succeeds.
pythongh-151022: Fix remote debugging linetable reads
maurycy commented on Jun 9, 2026
@pablogsal The more I think about this... For the purpose of mach_vm_remap, I'm trying to measure the bias (ie: delta between the truth and what we report, with aliasing and sampling rates between 2-5MHz I started to wonder about it; spoiler: we're great here.) But the original issue reports heavy bias actually... linetable, qualname/filename and MAX_FRAMES (and this _sync_coordinator.py; unlucky person who accidentially uses this name too) drop the whole frame silently. Now, for a long-running profiler on a large-scale production system a heavy bias, like the one observed originally, makes the profiling not trustworthy, and time completely wasted. In other words, apart from making the limits realistic, I believe we should not drop the frames on limit but degrade
pablogsal commented on Jun 9, 2026
What kind of degradation did you have in mind? Emitting the frame with line unknown when the linetable read fails, or something more specific?
maurycy commented on Jun 9, 2026
Yes, only this, truncation or a placeholder in case of qualname/filename or MAX_FRAMES etc. I think. More than open for any other ideas.
Merge branch 'python:main' into pythongh-151022-remote-debugging-line…
pythongh-151022: Strengthen large linetable test
chris-eibl commented on Jul 18, 2026
FWIW, when profiling pystone.py1,
I also get a high error rate (about 30%) on Windows (if that makes a difference).
The attached PR doesn't help, and also from the errors I think this must be something different:
Lots of
Failed to parse initial frame in chain
ReadProcessMemory failed for PID 24180 at address 0xc0000000 (size 64, partial read 0 bytes): Windows error 998
ReadProcessMemory failed for PID 24180 at address 0xe7 (size 64, partial read 0 bytes): Windows error 299
Where ERROR_NOACCESS=998 and ERROR_PARTIAL_COPY=299, which all indicate reading from invalid memory (already quite obvious from the pointer values).
Footnotes
e.g. https://github.com/dundee/pybenchmarks/blob/master/bencher/programs/pystone/pystone.python3 ↩
pythongh-151022: Tighten linetable parsing bounds
goutamadwant commented on Jul 18, 2026
@chris-eibl Thanks for testing this on Windows. I updated the PR to use a 64 KiB line-table limit and removed the separate entry-count limit.
The ReadProcessMemory errors shown here occur while resolving the initial frame chain, before line-table parsing begins, so they appear to be a separate failure path from the large-line-table issue addressed by #151036.
Could you compare the same pystone run with --blocking? If the errors disappear, that would help determine whether the invalid frame addresses come from a race in the non-blocking snapshot path. I think the Windows frame-chain failure should otherwise be tracked separately so both problems remain independently reproducible. Let me know.
cc @maurycy
chris-eibl commented on Jul 18, 2026
Yeah, --blocking drastically reduces the error rate (after applying #152471). And I agree this is a different (and most probably only Windows related) issue.
chris-eibl commented on Jul 19, 2026
Having a closer look, I think this quote from the documentation
very much applies to pystone.py. I've just wondered about the high error rate without giving it a closer thought. Sorry for the noise here ...
sergey-miryanov commented on Jul 19, 2026
Some background from py-spy but the reason the same, IIUC: https://www.benfrederickson.com/why-python-needs-paused-during-profiling/
pythongh-151022: Fix remote debugging linetable reads (python#151036)
[3.15] gh-151022: Fix remote debugging linetable reads (GH-151036) (#…
Exclude CPython startup and line-table unwinding limits from profiler…