-
-
Notifications
You must be signed in to change notification settings - Fork 33.9k
gh-143423: Fix free-threaded build detection in sampling profiler #143426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
gh-143423: Fix free-threaded build detection in sampling profiler #143426
Conversation
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
@pablogsal up for review |
Lib/profiling/sampling/sample.py
Outdated
| opcodes=opcodes, skip_non_matching_threads=skip_non_matching_threads, | ||
| cache_frames=True, stats=self.collect_stats | ||
| ) | ||
| # FIX: Properly handle all_threads vs only_active_thread parameters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additionally, I have updated _new_unwinder to properly handle the all_threads vs only_active_thread parameters based on the detected build type.
I suggest reverting this change and open a separated PR for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vstinner I attempted to revert the changes to _new_unwinder as requested, but I found that they are actually required for the tests to pass.
If I revert to the original code, test_profiling fails because idle_worker threads are missing from the stats.
The Traceback:
test test_profiling failed -- Traceback (most recent call last):
File "/workspaces/cpython/Lib/test/test_profiling/test_sampling_profiler/test_modes.py", line 197, in test_cpu_mode_integration_filtering
self.assertIn("idle_worker", wall_mode_output)
AssertionError: 'idle_worker' not found in 'Captured 401 samples...
The Logic Error: The issue lies in the original code: only_active_thread=bool(self.all_threads)
When self.all_threads is True, this sets only_active_thread=True. This effectively hides idle threads, which contradicts the intention of all_threads and causes the test failure shown above.
It seems my main fix (correcting _FREE_THREADED_BUILD) unmasked this existing logic bug, as the code now enters this path where it previously didn't.
Given this dependency, is it okay to keep the _new_unwinder fix in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, the if self.all_threads: change should be merged first. But I still consider that it would be better to have 2 pull requests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vstinner I have updated the PR as requested.
- Refactored the
_new_unwinderlogic to use**kwargs, which removes the code duplication. - Reverted the
_FREE_THREADED_BUILDdetection fix.
This PR now focuses strictly on resolving the thread-handling logic bug. I will submit the build detection fix in a separate PR once this has been addressed.
Lib/profiling/sampling/sample.py
Outdated
| opcodes=opcodes, skip_non_matching_threads=skip_non_matching_threads, | ||
| cache_frames=True, stats=self.collect_stats | ||
| ) | ||
| # FIX: Properly handle all_threads vs only_active_thread parameters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, the if self.all_threads: change should be merged first. But I still consider that it would be better to have 2 pull requests.
Lib/profiling/sampling/sample.py
Outdated
| unwinder = _remote_debugging.RemoteUnwinder( | ||
| self.pid, only_active_thread=bool(self.all_threads), mode=self.mode, native=native, gc=gc, | ||
| opcodes=opcodes, skip_non_matching_threads=skip_non_matching_threads, | ||
| cache_frames=True, stats=self.collect_stats |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is almost the same as above. You should do something like:
kwargs = {}
if self.all_threads:
kwargs['all_threads' = self.all_threads
unwinder = _remote_debugging.RemoteUnwinder(..., **kwargs)|
cc @pablogsal |
Description
This PR corrects a logic error in
Lib/profiling/sampling/sample.pywhere_FREE_THREADED_BUILDwas incorrectly evaluated asTrueon Windows non-free-threaded builds whenPy_GIL_DISABLEDwas explicitly set to0.The detection has been updated from an
is not Nonecheck to abool()cast, which correctly handles:1->True0->FalseNone->False(standard builds)Additionally, I have updated
_new_unwinderto properly handle theall_threadsvsonly_active_threadparameters based on the detected build type.Tests
_FREE_THREADED_BUILDreturnsFalsewhensysconfig.get_config_var("Py_GIL_DISABLED")is0../python -m test test_profiling(Passed)._FREE_THREADED_BUILDmis-detected when Py_GIL_DISABLED is defined but set to 0 #143423