From dea93ce2a203a9b3aedf091faa6610d13d2b5aea Mon Sep 17 00:00:00 2001 From: An Long Date: Tue, 7 Jul 2026 08:36:26 +0900 Subject: [PATCH 1/3] gh-153068: Preserve cprofile enable errors (#153070) --- Lib/test/test_profiling/test_tracing_profiler.py | 5 +++-- .../Library/2026-07-05-16-09-31.gh-issue-153068.huY9Jh.rst | 2 ++ Modules/_lsprof.c | 1 - 3 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-07-05-16-09-31.gh-issue-153068.huY9Jh.rst diff --git a/Lib/test/test_profiling/test_tracing_profiler.py b/Lib/test/test_profiling/test_tracing_profiler.py index 3668e24e073ce4d..e9f55613b6cfbb8 100644 --- a/Lib/test/test_profiling/test_tracing_profiler.py +++ b/Lib/test/test_profiling/test_tracing_profiler.py @@ -118,8 +118,9 @@ def test_second_profiler(self): pr = self.profilerclass() pr2 = self.profilerclass() pr.enable() - self.assertRaises(ValueError, pr2.enable) - pr.disable() + self.addCleanup(pr.disable) + msg = f"tool {sys.monitoring.PROFILER_ID} is already in use" + self.assertRaisesRegex(ValueError, msg, pr2.enable) def test_throw(self): """ diff --git a/Misc/NEWS.d/next/Library/2026-07-05-16-09-31.gh-issue-153068.huY9Jh.rst b/Misc/NEWS.d/next/Library/2026-07-05-16-09-31.gh-issue-153068.huY9Jh.rst new file mode 100644 index 000000000000000..accf6e99cd6434d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-05-16-09-31.gh-issue-153068.huY9Jh.rst @@ -0,0 +1,2 @@ +Fix :meth:`!cProfile.Profile.enable` to no longer overwrite errors from +:mod:`sys.monitoring`. diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 3d341a336ab22e6..4e50ca64f59af22 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -821,7 +821,6 @@ _lsprof_Profiler_enable_impl(ProfilerObject *self, int subcalls, "use_tool_id", "is", self->tool_id, "cProfile"); if (check == NULL) { - PyErr_Format(PyExc_ValueError, "Another profiling tool is already active"); goto error; } Py_DECREF(check); From d7275d356916f839dc96aaa43a75e0bbde25732e Mon Sep 17 00:00:00 2001 From: Duprat Date: Tue, 7 Jul 2026 01:39:06 +0200 Subject: [PATCH 2/3] gh-140729: Fix the cProfile module when the executed script contains calls to multiprocessing.Process (#144715) Co-authored-by: Pablo Galindo Salgado --- Lib/profiling/tracing/__init__.py | 4 ++- .../test_profiling/test_tracing_profiler.py | 35 ++++++++++++++++++- ...-02-11-16-47-27.gh-issue-140729.2uTPQp.rst | 3 ++ 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-02-11-16-47-27.gh-issue-140729.2uTPQp.rst 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 e9f55613b6cfbb8..8a7070142b60eec 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 @@ -193,6 +192,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. From 35c6779c7b5c4c2e2d9723803996050b711da0dd Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 6 Jul 2026 16:54:16 -0700 Subject: [PATCH 3/3] gh-145177: Update Emscripten to 6.0.2 (#153235) Removes the patched `getentropy()` call since it has been included upstream. --- Platforms/emscripten/config.toml | 2 +- Python/emscripten_syscalls.c | 20 -------------------- configure | 2 -- configure.ac | 4 ---- 4 files changed, 1 insertion(+), 27 deletions(-) diff --git a/Platforms/emscripten/config.toml b/Platforms/emscripten/config.toml index 389d2ea66ce948e..0c65a6623c9798a 100644 --- a/Platforms/emscripten/config.toml +++ b/Platforms/emscripten/config.toml @@ -1,7 +1,7 @@ # Any data that can vary between Python versions is to be kept in this file. # This allows for blanket copying of the Emscripten build code between supported # Python versions. -emscripten-version = "6.0.0" +emscripten-version = "6.0.2" node-version = "24" test-args = [ "-m", "test", diff --git a/Python/emscripten_syscalls.c b/Python/emscripten_syscalls.c index b0c370ced36cc33..48ca208dedb14bb 100644 --- a/Python/emscripten_syscalls.c +++ b/Python/emscripten_syscalls.c @@ -293,26 +293,6 @@ int __syscall_poll(intptr_t fds, int nfds, int timeout) { return __block_for_int(p); } - -// Workaround for an Emscripten bug: getentropy(buffer, 1) returns the single -// byte of entropy as the return code. Fixed upstream by -// emscripten-core/emscripten#27122 -int __real_getentropy(void*, size_t); - -int __wrap_getentropy(void *buffer, size_t len) { - if (len != 1) { - return __real_getentropy(buffer, len); - } - // Length is 1. Workaround is to get two bytes of entropy and write the - // first one into the original target buffer. - uint8_t tmp[2]; - int ret = __real_getentropy(tmp, 2); - if (ret == 0) { - *(uint8_t *)buffer = tmp[0]; - } - return ret; -} - #include int syscall_ioctl_orig(int fd, int request, void* varargs) diff --git a/configure b/configure index 01faef615a3d5e1..76c58f7c3a463db 100755 --- a/configure +++ b/configure @@ -9803,8 +9803,6 @@ fi as_fn_append LINKFORSHARED " -sSTACK_SIZE=5MB" as_fn_append LINKFORSHARED " -sTEXTDECODER=2" - as_fn_append LDFLAGS_NODIST " -Wl,--wrap=getentropy" - if test "x$enable_wasm_dynamic_linking" = xyes then : diff --git a/configure.ac b/configure.ac index a9fe5c269618fcd..de7a3abb379e659 100644 --- a/configure.ac +++ b/configure.ac @@ -2411,10 +2411,6 @@ AS_CASE([$ac_sys_system], dnl Avoid bugs in JS fallback string decoding path AS_VAR_APPEND([LINKFORSHARED], [" -sTEXTDECODER=2"]) - dnl Workaround for a bug in Emscipten libc's getentropy. See - dnl __wrap_getentropy in Python/emscripten_syscalls.c. - AS_VAR_APPEND([LDFLAGS_NODIST], [" -Wl,--wrap=getentropy"]) - AS_VAR_IF([enable_wasm_dynamic_linking], [yes], [ AS_VAR_APPEND([LINKFORSHARED], [" -sMAIN_MODULE"]) ])