* [3.15] gh-153364: Make frame, coroutine, and task-waiter chain walks iterative and bounded (GH-153365) (#158813)
gh-153364: Make frame, coroutine, and task-waiter chain walks iterative and bounded (GH-153365)
* let me declare single limit
* use our new limit in process_frame_chain()
* add it in parse_async_frame_chain()
* parse_coro_chain()
* NEWS
* async in the message?
* test
* no race
* process_task_awaited_by
* process_task_awaited_by limit test
* NEWS
* MAX_TASK_WAITER_CHAIN_DEPTH
* TASK_WAITER_CHAIN_DEPTH in test
* TASK_WAITER_CHAIN_DEPTH 256
* prevent the drift with the comment
* better naming, better style
* MAX_TASK_WAITER_CHAIN_DEPTH comment
* task-waiter iterative bfs walk
* iterative coro-walk
* nicer news
* 1 << 14
* comment
* unused read_Py_ssize_t
* fix tombstones
* simplify
* correct msg
* better test
* news for tombstones
* left-over from when testing buggy version
* redundant new line
(cherry picked from commit e0861c6ae7)
Co-authored-by: Maurycy Pawłowski-Wieroński <maurycy@maurycy.com>
(cherry picked from commit 9e401cf7f5)
* [3.15] gh-155811: Add a seqcount to `gc_stats` to prevent torn reads (GH-155828) (#158829)
* update_seq
* no need for XCHGL, MOVL is enough?
* gh-155811: Retry an inconsistent GC snapshot once
---------
(cherry picked from commit 5fecd448bb)
Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 028124039c)
* [3.15] gh-151292: `_remote_debugging`: Do not corrupt the binary file when hitting `OverflowError` (GH-152892) (#158830)
gh-151292: `_remote_debugging`: Do not corrupt the binary file when hitting `OverflowError` (GH-152892)
* the kolektor
* test
* better test
* news
* =Q, move const to the base, not self.running
* gh-151292: Track binary writer finalization state
---------
(cherry picked from commit f839c061d3)
Co-authored-by: Maurycy Pawłowski-Wieroński <maurycy@maurycy.com>
Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>
(cherry picked from commit 8a7c23f316)
* [3.15] gh-158583: Fix uninitialized memory read in bytes.fromhex() (GH-158584) (#158691)
gh-158583: Fix uninitialized memory read in bytes.fromhex() (GH-158584)
(cherry picked from commit 9d22a5334b)
Co-authored-by: Victor Stinner <vstinner@python.org>
(cherry picked from commit 4f7af46e25)
* [3.15] gh-154194: Degrade frames in Tachyon instead of failing the sample (GH-154195) (#158831)
* gh-154194: Degrade frames in Tachyon instead of failing the sample (#154195)
* degrade gracefully
* news
* better NEWS wording
* do not raise on MAX_REMOTE_STR_READ
* bye MAX_REMOTE_STR_READ
* fix -m asyncio ps|pstree
* test truncation and linetable sentinel
* simpler
* simpler
* redundant now
* respect #157790 in the news
---------
Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>
(cherry picked from commit 7d25916b41)
* Preserve the stable ABI when creating fallback frame names
---------
Co-authored-by: Maurycy Pawłowski-Wieroński <maurycy@maurycy.com>
(cherry picked from commit c27f494061)
* [3.15] Add MSan to CI (GH-158625) (#158832)
Run a job that the test suite with MSan to the CI (#158625)
* Run the test suite with MSan in CI
* Additional fixes
* Add `_Py_MSAN_UNPOISON_STRING`
* Apply Victor's suggestions
* Apply Victor's suggestions
---------
(cherry picked from commit b93fb19a6e)
Co-authored-by: Stan Ulbrych <stan@python.org>
Co-authored-by: Victor Stinner <victor.stinner@gmail.com>
(cherry picked from commit 1bc78dea18)
* [3.15] gh-156810: Write the profiler's collapsed-stack export as UTF-8 (GH-156811) (#156814)
gh-156810: Write the profiler's collapsed-stack export as UTF-8 (GH-156811)
(cherry picked from commit c3706f4c68)
Co-authored-by: tonghuaroot (童话) <tonghuaroot@gmail.com>
(cherry picked from commit fce28da9b7)
* [3.15] gh-158552: Wait for Windows threads to suspend before blocking sampling (GH-158802) (#158845)
gh-158552: Wait for Windows threads to suspend before blocking sampling (GH-158802)
* gh-158552: Wait for Windows threads to suspend before blocking sampling
* Use a named Windows thread enumeration status constant
(cherry picked from commit 1643525f0f)
Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>
(cherry picked from commit 31288da21d)
* [3.15] gh-152721: Fix quadratic RLE replay time in the profiling binary reader (GH-152722) (#158850)
Backport of GH-152722.
Co-authored-by: tonghuaroot <tonghuaroot@gmail.com>
(cherry picked from commit ebaca2ac2d)
* [3.15] gh-156545: Fix flamegraph export RecursionError on deeply recursive programs (GH-156546) (#158851)
Backport of GH-156546.
Co-authored-by: tonghuaroot (童话) <tonghuaroot@gmail.com>
(cherry picked from commit 0ac7217040)
* [3.15] gh-158540: Add the profiled script's directory to sys.path (GH-158548) (#158844)
gh-158540: Add the profiled script's directory to sys.path (GH-158548)
* gh-158540: Add the profiled script's directory to sys.path
When a script is profiled with ``python -m profiling.sampling run
script.py`` from another directory, the script cannot import modules
placed next to it, because ``_sync_coordinator._execute_script()``
executes it with the working directory (added by
``_setup_environment()`` for the module case) as ``sys.path[0]``
instead of the script's own directory.
Make the script's directory importable in ``_execute_script()``,
matching the behavior of ``python script.py``.
Add a regression test that runs the coordinator on a script importing
a sibling module.
* Update _sync_coordinator.py Comment simplified
* gh-158540: Resolve symlinks when adding the script directory to sys.path
``python script.py`` resolves symlinks when computing ``sys.path[0]``, so
a script reached through a symlink (``link.py -> sub/where.py``) imports
modules from the real script's directory. Apply ``os.path.realpath()``
before taking the directory name, and make sure the result is placed at
the front of ``sys.path`` even if it was already listed.
Add a regression test for a symlinked script.
---------
(cherry picked from commit 3f02aab9fa)
Co-authored-by: he_tao <53343436+hetaozdh@users.noreply.github.com>
Co-authored-by: Eduardo Villalpando Mello <eduardo.villalpando.mello@gmail.com>
(cherry picked from commit f52d831397)
* [3.15] gh-153838: Skip non-regular source files in the heatmap exporter (GH-153839) (#158853)
Backport of GH-153839.
Co-authored-by: tonghuaroot <tonghuaroot@gmail.com>
(cherry picked from commit 48998df251)
* [3.15] gh-158539: Fix exception mode missing handlers in generators/coroutines (GH-158581) (#158852)
* [3.15] gh-158539: Fix exception mode missing handlers in generators/coroutines (GH-158581)
Backport of GH-158581.
Co-authored-by: LucasZhou <donghao.zhou@outlook.com>
* [3.15] gh-158539: Use portable static assertion messages
* [3.15] gh-158539: Keep layout assertions with debug-offset validation
* [3.15] gh-158539: Use the platform guard for in-process inspection tests
---------
Co-authored-by: LucasZhou <donghao.zhou@outlook.com>
(cherry picked from commit d625ecbb8d)
* [3.15] gh-158522: Fix truncated stack for a task whose coroutine recurses (GH-158526) (#158870)
Co-authored-by: Timofei Ivankov <128279579+deadlovelll@users.noreply.github.com>
(cherry picked from commit a904b397ed)
* gh-156545, gh-158539: Fix deep flamegraph export on small C stacks and macOS runtime lookup (#158874)
(cherry picked from commit 114de198c0)
Include the C-stack test helper from main, introduced by
ce5ae29ef9, which the regression test
requires but 3.15 does not yet provide.
---------
Co-authored-by: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Co-authored-by: Maurycy Pawłowski-Wieroński <maurycy@maurycy.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Victor Stinner <vstinner@python.org>
Co-authored-by: Stan Ulbrych <stan@python.org>
Co-authored-by: Victor Stinner <victor.stinner@gmail.com>
Co-authored-by: tonghuaroot (童话) <tonghuaroot@gmail.com>
Co-authored-by: he_tao <53343436+hetaozdh@users.noreply.github.com>
Co-authored-by: Eduardo Villalpando Mello <eduardo.villalpando.mello@gmail.com>
Co-authored-by: LucasZhou <donghao.zhou@outlook.com>
Co-authored-by: Timofei Ivankov <128279579+deadlovelll@users.noreply.github.com>
* gh-154194: Degrade frames in Tachyon instead of failing the sample (#154195)
* degrade gracefully
* news
* better NEWS wording
* do not raise on MAX_REMOTE_STR_READ
* bye MAX_REMOTE_STR_READ
* fix -m asyncio ps|pstree
* test truncation and linetable sentinel
* simpler
* simpler
* redundant now
* respect #157790 in the news
---------
Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>
(cherry picked from commit 7d25916b41)
* Preserve the stable ABI when creating fallback frame names
---------
Co-authored-by: Maurycy Pawłowski-Wieroński <maurycy@maurycy.com>
gh-157549: Use sysconf() for the page size in remote_debug.h (GH-157800)
getpagesize() is not an ISO C or POSIX function. Darwin hides the prototype under -std=c11, so the _remote_debugging build fails with -Werror=implicit-function-declaration. That is the failure in the reported x86_64-apple-darwin → arm64-apple-darwin cross build.
Call sysconf(_SC_PAGESIZE) instead, which is already how resource.getpagesize() works. Fall back to 4096 if sysconf() fails.
--without-remote-debug is unchanged. That flag only disables the target-side attach protocol (Py_REMOTE_DEBUG); it does not exclude the _remote_debugging client module.
(cherry picked from commit 9193375382)
Co-authored-by: ノウラ | Flare <nouraellm@gmail.com>
gh-151029: Fix sys.remote_exec() unable to find writable memory when libpython replaced on disk (GH-151032)
(cherry picked from commit a69d0fc41e)
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
Co-authored-by: Pablo Galindo <pablogsal@gmail.com>
gh-149619: Fix `_remote_debugging` permissions error on Linux (GH-150012)
When running profiling on Linux without sudo, attempts to read
process memory would fail with the misleading error 'Failed to find
the PyRuntime section in process <pid> on Linux platform'.
The actual issue is a permissions error because profiling was not
run with sudo. We were clearing the exception on Linux when trying
to read memory, instead, we should bubble up the permissions error
and show it properly.
(cherry picked from commit 0563890872)
Co-authored-by: ivonastojanovic <80911834+ivonastojanovic@users.noreply.github.com>
When _ctypes is imported, it may call dlopen on the libpython shared
library, causing the dynamic linker to load a second mapping of the
library into the process address space. The remote debugging code
iterates memory regions from low addresses upward and returns the first
mapping whose filename matches libpython. After _ctypes is imported, it
finds the dlopen'd copy first, but that copy's PyRuntime section was
never initialized, so reading debug offsets from it fails.
Fix this by validating each candidate PyRuntime address before accepting
it. The validation reads the first 8 bytes and checks for the "xdebugpy"
cookie that is only present in an initialized PyRuntime. Uninitialized
duplicate mappings will fail this check and be skipped, allowing the
search to continue to the real, initialized PyRuntime.
This PR implements frame caching in the RemoteUnwinder class to significantly reduce memory reads when profiling remote processes with deep call stacks.
When cache_frames=True, the unwinder stores the frame chain from each sample and reuses unchanged portions in subsequent samples. Since most profiling samples capture similar call stacks (especially the parent frames), this optimization avoids repeatedly reading the same frame data from the target process.
The implementation adds a last_profiled_frame field to the thread state that tracks where the previous sample stopped. On the next sample, if the current frame chain reaches this marker, the cached frames from that point onward are reused instead of being re-read from remote memory.
The sampling profiler now enables frame caching by default.
Implement a statistical sampling profiler that can profile external
Python processes by PID. Uses the _remote_debugging module and converts
the results to pstats-compatible format for analysis.
Co-authored-by: Pablo Galindo <pablogsal@gmail.com>
Completely refactor Modules/_remote_debugging_module.c with improved
code organization, replacing scattered reference counting and error
handling with centralized goto error paths. This cleanup improves
maintainability and reduces code duplication throughout the module while
preserving the same external API.
Implement memory page caching optimization in Python/remote_debug.h to
avoid repeated reads of the same memory regions during debugging
operations. The cache stores previously read memory pages and reuses
them for subsequent reads, significantly reducing system calls and
improving performance.
Add code object caching mechanism with a new code_object_generation
field in the interpreter state that tracks when code object caches need
invalidation. This allows efficient reuse of parsed code object metadata
and eliminates redundant processing of the same code objects across
debugging sessions.
Optimize memory operations by replacing multiple individual structure
copies with single bulk reads for the same data structures. This reduces
the number of memory operations and system calls required to gather
debugging information from the target process.
Update Makefile.pre.in to include Python/remote_debug.h in the headers
list, ensuring that changes to the remote debugging header force proper
recompilation of dependent modules and maintain build consistency across
the codebase.
Also, make the module compatible with the free threading build as an extra :)
Co-authored-by: Łukasz Langa <lukasz@langa.pl>