Fixes #159117.
profiler_dealloc() still called _PyEval_SetProfile(tstate, NULL, NULL), although _lsprof now uses sys.monitoring. Destroying an enabled profiler after its monitoring callbacks have been released therefore cleared an unrelated sys.setprofile() callback.
When a cyclic profiler is collected during ProfileTest.do_profiling(), this can stop the pure Python profiler before it has recorded all calls, producing empty or partial statistics.
Remove the obsolete cleanup and its unused headers. Monitoring callbacks hold references to the profiler while registered, so deallocation does not need to unregister them. Add a deterministic regression test that releases an enabled profiler's monitoring callbacks, destroys it, and verifies that an independent sys.setprofile() callback remains installed. Include a NEWS entry.
Validation on a Windows AMD64 CPython 3.16 debug build:
- The new regression test fails before the C change (
sys.getprofile() returns None) and passes afterward.
PCbuild\amd64\python_d.exe -m test -j2 test_profile test_profiling test_sys_setprofile test_monitoring test_pstats passes (629 tests reported, 16 skipped).
PCbuild\amd64\python_d.exe -m test -j1 -R3:3 test_profile test.test_profiling.test_tracing_profiler passes with no detected reference leaks.
- Ruff, sphinx-lint,
git diff --cached --check, and CPython patchcheck pass.
The original Windows PGO tail-call and s390x buildbot configurations were not tested locally.