https://github.com/python/cpython/commit/81986cbdaa8e6721c0612df5d8feb1524643363a
commit: 81986cbdaa8e6721c0612df5d8feb1524643363a
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: pablogsal <[email protected]>
date: 2026-07-07T00:10:18Z
summary:
[3.15] gh-140729: Fix the cProfile module when the executed script contains
calls to multiprocessing.Process (GH-144715) (#153243)
files:
A Misc/NEWS.d/next/Library/2026-02-11-16-47-27.gh-issue-140729.2uTPQp.rst
M Lib/profiling/tracing/__init__.py
M Lib/test/test_profiling/test_tracing_profiler.py
diff --git a/Lib/profiling/tracing/__init__.py
b/Lib/profiling/tracing/__init__.py
index bd3cbf299aab3b9..165665304e05a40 100644
--- a/Lib/profiling/tracing/__init__.py
+++ b/Lib/profiling/tracing/__init__.py
@@ -197,7 +197,9 @@ def main():
# in the module's namespace.
globs = module.__dict__
globs.update({
- '__spec__': spec,
+ # Set __spec__ to None so the profiled program behaves like a
+ # script run directly (gh-140729).
+ '__spec__': None,
'__file__': spec.origin,
'__name__': spec.name,
'__package__': None,
diff --git a/Lib/test/test_profiling/test_tracing_profiler.py
b/Lib/test/test_profiling/test_tracing_profiler.py
index 3668e24e073ce4d..a4fabe9d3cc75bf 100644
--- a/Lib/test/test_profiling/test_tracing_profiler.py
+++ b/Lib/test/test_profiling/test_tracing_profiler.py
@@ -1,5 +1,4 @@
"""Test suite for the cProfile module."""
-
import sys
import unittest
@@ -192,6 +191,40 @@ class Foo:
f.close()
assert_python_ok('-m', "cProfile", f.name)
+ def _test_process_run_pickle(self, start_method):
+ val = 10
+ with tempfile.NamedTemporaryFile("w+", delete_on_close=False) as f:
+ f.write(textwrap.dedent(
+ f'''\
+ import multiprocessing
+
+ def worker(x):
+ print(__name__)
+ exit(x ** 2)
+
+ if __name__ == "__main__":
+ multiprocessing.set_start_method('{start_method}')
+ p = multiprocessing.Process(target=worker, args=({val},))
+ p.start()
+ p.join()
+ print("p.exitcode =", p.exitcode)
+ '''))
+ f.close()
+ _, out, err = assert_python_ok('-m', "cProfile", f.name)
+ self.assertIn(b"__mp_main__", out)
+ self.assertIn(bytes(f"exitcode = {val**2}", encoding='utf8'), out)
+ self.assertNotIn(b"Can't pickle", err)
+
+ def test_process_spawn_pickle(self):
+ # gh-140729: test use Process in cProfile.
+ self._test_process_run_pickle('spawn')
+
+ @unittest.skipIf(sys.platform == 'win32',
+ "No 'forkserver' start method on Windows")
+ def test_process_forkserver_pickle(self):
+ # gh-140729: test use Process in cProfile.
+ self._test_process_run_pickle('forkserver')
+
def main():
if '-r' not in sys.argv:
diff --git
a/Misc/NEWS.d/next/Library/2026-02-11-16-47-27.gh-issue-140729.2uTPQp.rst
b/Misc/NEWS.d/next/Library/2026-02-11-16-47-27.gh-issue-140729.2uTPQp.rst
new file mode 100644
index 000000000000000..49c9adc4679abbf
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-02-11-16-47-27.gh-issue-140729.2uTPQp.rst
@@ -0,0 +1,3 @@
+Fix a pickling error in the ``cProfile`` module when profiling a script that
+uses :class:`multiprocessing.Process` with the ``spawn`` and ``forkserver``
+start methods.
_______________________________________________
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]