https://github.com/python/cpython/commit/37b238f1a6f0d8738e44ccc516ca2a476c38e5ce
commit: 37b238f1a6f0d8738e44ccc516ca2a476c38e5ce
branch: main
author: Zain Nadeem <[email protected]>
committer: pablogsal <[email protected]>
date: 2026-06-28T18:58:56+02:00
summary:
gh-152356: Fix Windows blocking sampling after target process exit (#152471)
files:
A Misc/NEWS.d/next/Library/2026-06-28-12-45-09.gh-issue-152356.Dr4w2Q.rst
M Lib/test/test_profiling/test_sampling_profiler/test_blocking.py
M Modules/_remote_debugging/threads.c
diff --git a/Lib/test/test_profiling/test_sampling_profiler/test_blocking.py
b/Lib/test/test_profiling/test_sampling_profiler/test_blocking.py
index 1f4b6da32810561..0a5541c733d4c77 100644
--- a/Lib/test/test_profiling/test_sampling_profiler/test_blocking.py
+++ b/Lib/test/test_profiling/test_sampling_profiler/test_blocking.py
@@ -1,6 +1,9 @@
"""Tests for blocking mode sampling profiler."""
import io
+import os
+import subprocess
+import sys
import textwrap
import unittest
from unittest import mock
@@ -15,7 +18,11 @@
"Test only runs when _remote_debugging is available"
)
-from test.support import requires_remote_subprocess_debugging
+from test.support import (
+ SHORT_TIMEOUT,
+ os_helper,
+ requires_remote_subprocess_debugging,
+)
from .helpers import test_subprocess
@@ -158,3 +165,51 @@ def test_generator_not_under_consumer_arithmetic(self):
f"fibonacci_generator appears in the stack when consume_generator "
f"is the leaf frame on an arithmetic line. This indicates "
f"torn/inconsistent stack traces are being captured.")
+
+
+@requires_remote_subprocess_debugging()
[email protected](sys.platform == "win32", "Windows only")
+class TestBlockingModeCLI(unittest.TestCase):
+ def test_run_blocking_exits_after_target_process_exits(self):
+ script = 'print("done")\n'
+
+ tmpdir = os.path.abspath(os_helper.TESTFN + "_profiling_blocking")
+ with os_helper.temp_dir(tmpdir) as tmpdir:
+ script_path = os.path.join(tmpdir, "tiny_target.py")
+ profile_path = os.path.join(tmpdir, "blocking.bin")
+ with open(script_path, "w", encoding="utf-8") as file:
+ file.write(script)
+
+ cmd = [
+ sys.executable, "-m", "profiling.sampling", "run",
+ "--binary", "-o", profile_path,
+ "--mode=cpu", "--blocking", "-r", "100",
+ script_path,
+ ]
+ result = subprocess.run(
+ cmd,
+ cwd=tmpdir,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True,
+ timeout=SHORT_TIMEOUT,
+ )
+
+ self.assertEqual(
+ result.returncode, 0,
+ f"stdout:\n{result.stdout}\nstderr:\n{result.stderr}",
+ )
+ self.assertGreater(os.path.getsize(profile_path), 0)
+
+ replay = subprocess.run(
+ [sys.executable, "-m", "profiling.sampling", "replay",
+ profile_path],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True,
+ timeout=SHORT_TIMEOUT,
+ )
+ self.assertEqual(
+ replay.returncode, 0,
+ f"stdout:\n{replay.stdout}\nstderr:\n{replay.stderr}",
+ )
diff --git
a/Misc/NEWS.d/next/Library/2026-06-28-12-45-09.gh-issue-152356.Dr4w2Q.rst
b/Misc/NEWS.d/next/Library/2026-06-28-12-45-09.gh-issue-152356.Dr4w2Q.rst
new file mode 100644
index 000000000000000..6a4ceecbe9279e2
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-06-28-12-45-09.gh-issue-152356.Dr4w2Q.rst
@@ -0,0 +1,3 @@
+Fix a hang in ``profiling.sampling run --blocking`` on Windows when the
+target process exits. The profiler now finalizes binary profiles instead of
+continuing to sample the exited process.
diff --git a/Modules/_remote_debugging/threads.c
b/Modules/_remote_debugging/threads.c
index 29f22f14c9b29f8..04c70cc96d6bd1e 100644
--- a/Modules/_remote_debugging/threads.c
+++ b/Modules/_remote_debugging/threads.c
@@ -862,6 +862,12 @@ _Py_RemoteDebug_StopAllThreads(RemoteUnwinderObject
*unwinder, _Py_RemoteDebug_T
return 0;
}
+ if (!is_process_alive(unwinder->handle.hProcess)) {
+ PyErr_Format(PyExc_ProcessLookupError,
+ "Process %d has terminated", unwinder->handle.pid);
+ return -1;
+ }
+
PyErr_Format(PyExc_RuntimeError, "NtSuspendProcess failed: 0x%lx", status);
return -1;
}
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]