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]

Reply via email to