diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst index 9c0b828fbd4d28..d82dda9e54b150 100644 --- a/Doc/library/mmap.rst +++ b/Doc/library/mmap.rst @@ -289,6 +289,8 @@ To map anonymous memory, -1 should be passed as the fileno along with the length pagefile) will silently create a new map with the original data copied over up to the length of the new size. + Availability: Windows and systems with the ``mremap()`` system call. + .. versionchanged:: 3.11 Correctly fails if attempting to resize when another map is held Allows resize against an anonymous map on Windows diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 351ba0cd2afdfe..3236213de5aaa2 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -701,6 +701,9 @@ Porting to Python 3.15 :func:`resource.setrlimit` and :func:`resource.prlimit` is now deprecated. (Contributed by Serhiy Storchaka in :gh:`137044`.) +* :meth:`~mmap.mmap.resize` has been removed on platforms that don't support the + underlying syscall, instead of raising a :exc:`SystemError`. + Deprecated C APIs ----------------- diff --git a/Lib/test/test_free_threading/test_cprofile.py b/Lib/test/test_free_threading/test_cprofile.py new file mode 100644 index 00000000000000..361b800d6b9029 --- /dev/null +++ b/Lib/test/test_free_threading/test_cprofile.py @@ -0,0 +1,43 @@ +import unittest + +from test.support import threading_helper + +import cProfile +import pstats + + +NTHREADS = 10 +INSERT_PER_THREAD = 1000 + + +@threading_helper.requires_working_threading() +class TestCProfile(unittest.TestCase): + def test_cprofile_racing_list_insert(self): + def list_insert(lst): + for i in range(INSERT_PER_THREAD): + lst.insert(0, i) + + lst = [] + + with cProfile.Profile() as pr: + threading_helper.run_concurrently( + worker_func=list_insert, nthreads=NTHREADS, args=(lst,) + ) + pr.create_stats() + ps = pstats.Stats(pr) + stats_profile = ps.get_stats_profile() + list_insert_profile = stats_profile.func_profiles[ + "" + ] + # Even though there is no explicit recursive call to insert, + # cProfile may record some calls as recursive due to limitations + # in its handling of multithreaded programs. This issue is not + # directly related to FT Python itself; however, it tends to be + # more noticeable when using FT Python. Therefore, consider only + # the calls section and disregard the recursive part. + list_insert_ncalls = list_insert_profile.ncalls.split("/")[0] + self.assertEqual( + int(list_insert_ncalls), NTHREADS * INSERT_PER_THREAD + ) + + self.assertEqual(len(lst), NTHREADS * INSERT_PER_THREAD) diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py index da69770915092a..75ea1a671b67de 100644 --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -57,6 +57,7 @@ def test_basic(self): f.write(b'\0'* (PAGESIZE-3) ) f.flush() m = mmap.mmap(f.fileno(), 2 * PAGESIZE) + self.addCleanup(m.close) finally: f.close() @@ -114,31 +115,28 @@ def test_basic(self): # Try to seek to negative position... self.assertRaises(ValueError, m.seek, -len(m)-1, 2) + @unittest.skipUnless(hasattr(mmap.mmap, 'resize'), 'requires mmap.resize') + def test_resize(self): + # Create a file to be mmap'ed. + with open(TESTFN, 'bw+') as f: + # Write 2 pages worth of data to the file + f.write(b'\0'* 2 * PAGESIZE) + f.flush() + m = mmap.mmap(f.fileno(), 2 * PAGESIZE) + self.addCleanup(m.close) + # Try resizing map - try: - m.resize(512) - except SystemError: - # resize() not supported - # No messages are printed, since the output of this test suite - # would then be different across platforms. - pass - else: - # resize() is supported - self.assertEqual(len(m), 512) - # Check that we can no longer seek beyond the new size. - self.assertRaises(ValueError, m.seek, 513, 0) - - # Check that the underlying file is truncated too - # (bug #728515) - f = open(TESTFN, 'rb') - try: - f.seek(0, 2) - self.assertEqual(f.tell(), 512) - finally: - f.close() - self.assertEqual(m.size(), 512) + m.resize(512) + self.assertEqual(len(m), 512) + # Check that we can no longer seek beyond the new size. + self.assertRaises(ValueError, m.seek, 513, 0) - m.close() + # Check that the underlying file is truncated too + # (bug #728515) + with open(TESTFN, 'rb') as f: + f.seek(0, 2) + self.assertEqual(f.tell(), 512) + self.assertEqual(m.size(), 512) def test_access_parameter(self): # Test for "access" keyword parameter @@ -183,15 +181,10 @@ def test_access_parameter(self): else: self.fail("Able to write to readonly memory map") - # Ensuring that readonly mmap can't be resized - try: - m.resize(2*mapsize) - except SystemError: # resize is not universally supported - pass - except TypeError: - pass - else: - self.fail("Able to resize readonly memory map") + if hasattr(m, 'resize'): + # Ensuring that readonly mmap can't be resized + with self.assertRaises(TypeError): + m.resize(2 * mapsize) with open(TESTFN, "rb") as fp: self.assertEqual(fp.read(), b'a'*mapsize, "Readonly memory map data file was modified") @@ -242,8 +235,9 @@ def test_access_parameter(self): with open(TESTFN, "rb") as fp: self.assertEqual(fp.read(), b'c'*mapsize, "Copy-on-write test data file should not be modified.") - # Ensuring copy-on-write maps cannot be resized - self.assertRaises(TypeError, m.resize, 2*mapsize) + if hasattr(m, 'resize'): + # Ensuring copy-on-write maps cannot be resized + self.assertRaises(TypeError, m.resize, 2 * mapsize) m.close() # Ensuring invalid access parameter raises exception @@ -282,10 +276,11 @@ def test_trackfd_parameter(self, close_original_fd): self.assertEqual(len(m), size) with self.assertRaises(ValueError): m.size() - with self.assertRaises(ValueError): - m.resize(size * 2) - with self.assertRaises(ValueError): - m.resize(size // 2) + if hasattr(m, 'resize'): + with self.assertRaises(ValueError): + m.resize(size * 2) + with self.assertRaises(ValueError): + m.resize(size // 2) self.assertIs(m.closed, False) # Smoke-test other API @@ -313,8 +308,9 @@ def test_trackfd_neg1(self): with mmap.mmap(-1, size, trackfd=False) as m: with self.assertRaises(ValueError): m.size() - with self.assertRaises(ValueError): - m.resize(size // 2) + if hasattr(m, 'resize'): + with self.assertRaises(ValueError): + m.resize(size // 2) self.assertEqual(len(m), size) m[0] = ord('a') assert m[0] == ord('a') @@ -608,13 +604,9 @@ def test_offset (self): self.assertEqual(m[0:3], b'foo') f.close() - # Try resizing map - try: + if hasattr(m, 'resize'): + # Try resizing map m.resize(512) - except SystemError: - pass - else: - # resize() is supported self.assertEqual(len(m), 512) # Check that we can no longer seek beyond the new size. self.assertRaises(ValueError, m.seek, 513, 0) @@ -806,14 +798,12 @@ def test_write_returning_the_number_of_bytes_written(self): self.assertEqual(mm.write(b"yz"), 2) self.assertEqual(mm.write(b"python"), 6) + @unittest.skipUnless(hasattr(mmap.mmap, 'resize'), 'requires mmap.resize') def test_resize_past_pos(self): m = mmap.mmap(-1, 8192) self.addCleanup(m.close) m.read(5000) - try: - m.resize(4096) - except SystemError: - self.skipTest("resizing not supported") + m.resize(4096) self.assertEqual(m.read(14), b'') self.assertRaises(ValueError, m.read_byte) self.assertRaises(ValueError, m.write_byte, 42) @@ -895,6 +885,7 @@ def test_madvise(self): self.assertEqual(m.madvise(mmap.MADV_NORMAL, 0, 2), None) self.assertEqual(m.madvise(mmap.MADV_NORMAL, 0, size), None) + @unittest.skipUnless(hasattr(mmap.mmap, 'resize'), 'requires mmap.resize') def test_resize_up_anonymous_mapping(self): """If the mmap is backed by the pagefile ensure a resize up can happen and that the original data is still in place @@ -911,16 +902,13 @@ def test_resize_up_anonymous_mapping(self): with self.assertRaises(ValueError): m.resize(new_size) else: - try: - m.resize(new_size) - except SystemError: - pass - else: - self.assertEqual(len(m), new_size) - self.assertEqual(m[:start_size], data) - self.assertEqual(m[start_size:], b'\0' * (new_size - start_size)) + m.resize(new_size) + self.assertEqual(len(m), new_size) + self.assertEqual(m[:start_size], data) + self.assertEqual(m[start_size:], b'\0' * (new_size - start_size)) @unittest.skipUnless(os.name == 'posix', 'requires Posix') + @unittest.skipUnless(hasattr(mmap.mmap, 'resize'), 'requires mmap.resize') def test_resize_up_private_anonymous_mapping(self): start_size = PAGESIZE new_size = 2 * start_size @@ -928,15 +916,12 @@ def test_resize_up_private_anonymous_mapping(self): with mmap.mmap(-1, start_size, flags=mmap.MAP_PRIVATE) as m: m[:] = data - try: - m.resize(new_size) - except SystemError: - pass - else: - self.assertEqual(len(m), new_size) - self.assertEqual(m[:start_size], data) - self.assertEqual(m[start_size:], b'\0' * (new_size - start_size)) + m.resize(new_size) + self.assertEqual(len(m), new_size) + self.assertEqual(m[:start_size], data) + self.assertEqual(m[start_size:], b'\0' * (new_size - start_size)) + @unittest.skipUnless(hasattr(mmap.mmap, 'resize'), 'requires mmap.resize') def test_resize_down_anonymous_mapping(self): """If the mmap is backed by the pagefile ensure a resize down up can happen and that a truncated form of the original data is still in place @@ -947,17 +932,13 @@ def test_resize_down_anonymous_mapping(self): with mmap.mmap(-1, start_size) as m: m[:] = data - try: - m.resize(new_size) - except SystemError: - pass - else: - self.assertEqual(len(m), new_size) - self.assertEqual(m[:], data[:new_size]) - if sys.platform.startswith(('linux', 'android')): - # Can't expand to its original size. - with self.assertRaises(ValueError): - m.resize(start_size) + m.resize(new_size) + self.assertEqual(len(m), new_size) + self.assertEqual(m[:], data[:new_size]) + if sys.platform.startswith(('linux', 'android')): + # Can't expand to its original size. + with self.assertRaises(ValueError): + m.resize(start_size) @unittest.skipUnless(os.name == 'nt', 'requires Windows') def test_resize_fails_if_mapping_held_elsewhere(self): diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 6317d4657619f0..0fc5415c390145 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -9788,6 +9788,19 @@ class B(str): ... self.assertIs(type(field_c2.__metadata__[0]), float) self.assertIs(type(field_c3.__metadata__[0]), bool) + def test_forwardref_partial_evaluation(self): + # Test that Annotated partially evaluates if it contains a ForwardRef + # See: https://github.com/python/cpython/issues/137706 + def f(x: Annotated[undefined, '']): pass + + ann = annotationlib.get_annotations(f, format=annotationlib.Format.FORWARDREF) + + # Test that the attributes are retrievable from the partially evaluated annotation + x_ann = ann['x'] + self.assertIs(get_origin(x_ann), Annotated) + self.assertEqual(x_ann.__origin__, EqualToForwardRef('undefined', owner=f)) + self.assertEqual(x_ann.__metadata__, ('',)) + class TypeAliasTests(BaseTestCase): def test_canonical_usage_with_variable_annotation(self): diff --git a/Lib/typing.py b/Lib/typing.py index ea25e3832bd0be..babe3c44d9dc55 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1027,8 +1027,10 @@ def evaluate_forward_ref( def _is_unpacked_typevartuple(x: Any) -> bool: + # Need to check 'is True' here + # See: https://github.com/python/cpython/issues/137706 return ((not isinstance(x, type)) and - getattr(x, '__typing_is_unpacked_typevartuple__', False)) + getattr(x, '__typing_is_unpacked_typevartuple__', False) is True) def _is_typevar_like(x: Any) -> bool: diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-08-28-09-29-46.gh-issue-116738.yLZJpV.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-08-28-09-29-46.gh-issue-116738.yLZJpV.rst new file mode 100644 index 00000000000000..2bb68035b56509 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-08-28-09-29-46.gh-issue-116738.yLZJpV.rst @@ -0,0 +1,2 @@ +Make :mod:`cProfile` thread-safe on the :term:`free threaded ` build. diff --git a/Misc/NEWS.d/next/Library/2025-08-31-12-34-02.gh-issue-138205.iHXb1z.rst b/Misc/NEWS.d/next/Library/2025-08-31-12-34-02.gh-issue-138205.iHXb1z.rst new file mode 100644 index 00000000000000..0dd94324ffd2ea --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-08-31-12-34-02.gh-issue-138205.iHXb1z.rst @@ -0,0 +1,2 @@ +Removed the :meth:`~mmap.mmap.resize` method on platforms that don't support the +underlying syscall, instead of raising a :exc:`SystemError`. diff --git a/Misc/NEWS.d/next/Library/2025-09-05-21-10-24.gh-issue-137706.0EztiJ.rst b/Misc/NEWS.d/next/Library/2025-09-05-21-10-24.gh-issue-137706.0EztiJ.rst new file mode 100644 index 00000000000000..9eed50ec20a8f6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-09-05-21-10-24.gh-issue-137706.0EztiJ.rst @@ -0,0 +1 @@ +Fix the partial evaluation of annotations that use ``typing.Annotated[T, x]`` where ``T`` is a forward reference. diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index d0074b2a0d1f4d..c20dbc3f4f4bfb 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -534,6 +534,7 @@ static int statsForEntry(rotating_node_t *node, void *arg) } /*[clinic input] +@critical_section _lsprof.Profiler.getstats cls: defining_class @@ -565,7 +566,7 @@ profiler_subentry objects: static PyObject * _lsprof_Profiler_getstats_impl(ProfilerObject *self, PyTypeObject *cls) -/*[clinic end generated code: output=1806ef720019ee03 input=445e193ef4522902]*/ +/*[clinic end generated code: output=1806ef720019ee03 input=3dc69eb85ed73d91]*/ { statscollector_t collect; collect.state = _PyType_GetModuleState(cls); @@ -613,6 +614,7 @@ setBuiltins(ProfilerObject *pObj, int nvalue) } /*[clinic input] +@critical_section _lsprof.Profiler._pystart_callback code: object @@ -624,7 +626,7 @@ _lsprof.Profiler._pystart_callback static PyObject * _lsprof_Profiler__pystart_callback_impl(ProfilerObject *self, PyObject *code, PyObject *instruction_offset) -/*[clinic end generated code: output=5fec8b7ad5ed25e8 input=b166e6953c579cda]*/ +/*[clinic end generated code: output=5fec8b7ad5ed25e8 input=b61a0e79cf1f8499]*/ { ptrace_enter_call((PyObject*)self, (void *)code, code); @@ -632,6 +634,7 @@ _lsprof_Profiler__pystart_callback_impl(ProfilerObject *self, PyObject *code, } /*[clinic input] +@critical_section _lsprof.Profiler._pythrow_callback code: object @@ -645,7 +648,7 @@ static PyObject * _lsprof_Profiler__pythrow_callback_impl(ProfilerObject *self, PyObject *code, PyObject *instruction_offset, PyObject *exception) -/*[clinic end generated code: output=0a32988919dfb94c input=fd728fc2c074f5e6]*/ +/*[clinic end generated code: output=0a32988919dfb94c input=60c7f272206d3758]*/ { ptrace_enter_call((PyObject*)self, (void *)code, code); @@ -653,6 +656,7 @@ _lsprof_Profiler__pythrow_callback_impl(ProfilerObject *self, PyObject *code, } /*[clinic input] +@critical_section _lsprof.Profiler._pyreturn_callback code: object @@ -667,7 +671,7 @@ _lsprof_Profiler__pyreturn_callback_impl(ProfilerObject *self, PyObject *code, PyObject *instruction_offset, PyObject *retval) -/*[clinic end generated code: output=9e2f6fc1b882c51e input=667ffaeb2fa6fd1f]*/ +/*[clinic end generated code: output=9e2f6fc1b882c51e input=0ddcc1ec53faa928]*/ { ptrace_leave_call((PyObject*)self, (void *)code); @@ -703,6 +707,7 @@ PyObject* get_cfunc_from_callable(PyObject* callable, PyObject* self_arg, PyObje } /*[clinic input] +@critical_section _lsprof.Profiler._ccall_callback code: object @@ -717,7 +722,7 @@ static PyObject * _lsprof_Profiler__ccall_callback_impl(ProfilerObject *self, PyObject *code, PyObject *instruction_offset, PyObject *callable, PyObject *self_arg) -/*[clinic end generated code: output=152db83cabd18cad input=0e66687cfb95c001]*/ +/*[clinic end generated code: output=152db83cabd18cad input=2fc1e0630ee5e32b]*/ { if (self->flags & POF_BUILTINS) { PyObject* cfunc = get_cfunc_from_callable(callable, self_arg, self->missing); @@ -733,6 +738,7 @@ _lsprof_Profiler__ccall_callback_impl(ProfilerObject *self, PyObject *code, } /*[clinic input] +@critical_section _lsprof.Profiler._creturn_callback code: object @@ -748,7 +754,7 @@ _lsprof_Profiler__creturn_callback_impl(ProfilerObject *self, PyObject *code, PyObject *instruction_offset, PyObject *callable, PyObject *self_arg) -/*[clinic end generated code: output=1e886dde8fed8fb0 input=b18afe023746923a]*/ +/*[clinic end generated code: output=1e886dde8fed8fb0 input=bdc246d6b5b8714a]*/ { if (self->flags & POF_BUILTINS) { PyObject* cfunc = get_cfunc_from_callable(callable, self_arg, self->missing); @@ -780,6 +786,7 @@ static const struct { /*[clinic input] +@critical_section _lsprof.Profiler.enable subcalls: bool = True @@ -796,7 +803,7 @@ Start collecting profiling information. static PyObject * _lsprof_Profiler_enable_impl(ProfilerObject *self, int subcalls, int builtins) -/*[clinic end generated code: output=1e747f9dc1edd571 input=9ab81405107ab7f1]*/ +/*[clinic end generated code: output=1e747f9dc1edd571 input=0b88115b1c796173]*/ { int all_events = 0; if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) { @@ -869,6 +876,7 @@ flush_unmatched(ProfilerObject *pObj) /*[clinic input] +@critical_section _lsprof.Profiler.disable Stop collecting profiling information. @@ -876,7 +884,7 @@ Stop collecting profiling information. static PyObject * _lsprof_Profiler_disable_impl(ProfilerObject *self) -/*[clinic end generated code: output=838cffef7f651870 input=05700b3fc68d1f50]*/ +/*[clinic end generated code: output=838cffef7f651870 input=f7e4787cae20f7f6]*/ { if (self->flags & POF_EXT_TIMER) { PyErr_SetString(PyExc_RuntimeError, @@ -928,6 +936,7 @@ _lsprof_Profiler_disable_impl(ProfilerObject *self) } /*[clinic input] +@critical_section _lsprof.Profiler.clear Clear all profiling information collected so far. @@ -935,7 +944,7 @@ Clear all profiling information collected so far. static PyObject * _lsprof_Profiler_clear_impl(ProfilerObject *self) -/*[clinic end generated code: output=dd1c668fb84b1335 input=fbe1f88c28be4f98]*/ +/*[clinic end generated code: output=dd1c668fb84b1335 input=4aab219d5d7a9bec]*/ { if (self->flags & POF_EXT_TIMER) { PyErr_SetString(PyExc_RuntimeError, diff --git a/Modules/clinic/_lsprof.c.h b/Modules/clinic/_lsprof.c.h index c426cd6fe02f39..acb4aaf27e377f 100644 --- a/Modules/clinic/_lsprof.c.h +++ b/Modules/clinic/_lsprof.c.h @@ -6,6 +6,7 @@ preserve # include "pycore_gc.h" // PyGC_Head # include "pycore_runtime.h" // _Py_ID() #endif +#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION() #include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_lsprof_Profiler_getstats__doc__, @@ -45,11 +46,18 @@ _lsprof_Profiler_getstats_impl(ProfilerObject *self, PyTypeObject *cls); static PyObject * _lsprof_Profiler_getstats(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { + PyObject *return_value = NULL; + if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) { PyErr_SetString(PyExc_TypeError, "getstats() takes no arguments"); - return NULL; + goto exit; } - return _lsprof_Profiler_getstats_impl((ProfilerObject *)self, cls); + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _lsprof_Profiler_getstats_impl((ProfilerObject *)self, cls); + Py_END_CRITICAL_SECTION(); + +exit: + return return_value; } PyDoc_STRVAR(_lsprof_Profiler__pystart_callback__doc__, @@ -76,7 +84,9 @@ _lsprof_Profiler__pystart_callback(PyObject *self, PyObject *const *args, Py_ssi } code = args[0]; instruction_offset = args[1]; + Py_BEGIN_CRITICAL_SECTION(self); return_value = _lsprof_Profiler__pystart_callback_impl((ProfilerObject *)self, code, instruction_offset); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -109,7 +119,9 @@ _lsprof_Profiler__pythrow_callback(PyObject *self, PyObject *const *args, Py_ssi code = args[0]; instruction_offset = args[1]; exception = args[2]; + Py_BEGIN_CRITICAL_SECTION(self); return_value = _lsprof_Profiler__pythrow_callback_impl((ProfilerObject *)self, code, instruction_offset, exception); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -143,7 +155,9 @@ _lsprof_Profiler__pyreturn_callback(PyObject *self, PyObject *const *args, Py_ss code = args[0]; instruction_offset = args[1]; retval = args[2]; + Py_BEGIN_CRITICAL_SECTION(self); return_value = _lsprof_Profiler__pyreturn_callback_impl((ProfilerObject *)self, code, instruction_offset, retval); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -178,7 +192,9 @@ _lsprof_Profiler__ccall_callback(PyObject *self, PyObject *const *args, Py_ssize instruction_offset = args[1]; callable = args[2]; self_arg = args[3]; + Py_BEGIN_CRITICAL_SECTION(self); return_value = _lsprof_Profiler__ccall_callback_impl((ProfilerObject *)self, code, instruction_offset, callable, self_arg); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -215,7 +231,9 @@ _lsprof_Profiler__creturn_callback(PyObject *self, PyObject *const *args, Py_ssi instruction_offset = args[1]; callable = args[2]; self_arg = args[3]; + Py_BEGIN_CRITICAL_SECTION(self); return_value = _lsprof_Profiler__creturn_callback_impl((ProfilerObject *)self, code, instruction_offset, callable, self_arg); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -299,7 +317,9 @@ _lsprof_Profiler_enable(PyObject *self, PyObject *const *args, Py_ssize_t nargs, goto exit; } skip_optional_pos: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _lsprof_Profiler_enable_impl((ProfilerObject *)self, subcalls, builtins); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -320,7 +340,13 @@ _lsprof_Profiler_disable_impl(ProfilerObject *self); static PyObject * _lsprof_Profiler_disable(PyObject *self, PyObject *Py_UNUSED(ignored)) { - return _lsprof_Profiler_disable_impl((ProfilerObject *)self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _lsprof_Profiler_disable_impl((ProfilerObject *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(_lsprof_Profiler_clear__doc__, @@ -338,7 +364,13 @@ _lsprof_Profiler_clear_impl(ProfilerObject *self); static PyObject * _lsprof_Profiler_clear(PyObject *self, PyObject *Py_UNUSED(ignored)) { - return _lsprof_Profiler_clear_impl((ProfilerObject *)self); + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _lsprof_Profiler_clear_impl((ProfilerObject *)self); + Py_END_CRITICAL_SECTION(); + + return return_value; } PyDoc_STRVAR(profiler_init__doc__, @@ -444,4 +476,4 @@ profiler_init(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=9e46985561166c37 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=af26a0b0ddcc3351 input=a9049054013a1b77]*/ diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index dcaadb818e0bf7..8c9d463ad903ec 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -628,6 +628,7 @@ is_writable(mmap_object *self) return 0; } +#if defined(MS_WINDOWS) || defined(HAVE_MREMAP) static int is_resizeable(mmap_object *self) { @@ -648,6 +649,7 @@ is_resizeable(mmap_object *self) return 0; } +#endif /* MS_WINDOWS || HAVE_MREMAP */ static PyObject * @@ -766,6 +768,7 @@ mmap_size_method(PyObject *op, PyObject *Py_UNUSED(ignored)) / new size? */ +#if defined(MS_WINDOWS) || defined(HAVE_MREMAP) static PyObject * mmap_resize_method(PyObject *op, PyObject *args) { @@ -880,11 +883,6 @@ mmap_resize_method(PyObject *op, PyObject *args) #endif /* MS_WINDOWS */ #ifdef UNIX -#ifndef HAVE_MREMAP - PyErr_SetString(PyExc_SystemError, - "mmap: resizing not available--no mremap()"); - return NULL; -#else void *newmap; #ifdef __linux__ @@ -916,10 +914,10 @@ mmap_resize_method(PyObject *op, PyObject *args) self->data = newmap; self->size = new_size; Py_RETURN_NONE; -#endif /* HAVE_MREMAP */ #endif /* UNIX */ } } +#endif /* MS_WINDOWS || HAVE_MREMAP */ static PyObject * mmap_tell_method(PyObject *op, PyObject *Py_UNUSED(ignored)) @@ -1207,7 +1205,9 @@ static struct PyMethodDef mmap_object_methods[] = { {"read", mmap_read_method, METH_VARARGS}, {"read_byte", mmap_read_byte_method, METH_NOARGS}, {"readline", mmap_read_line_method, METH_NOARGS}, +#if defined(MS_WINDOWS) || defined(HAVE_MREMAP) {"resize", mmap_resize_method, METH_VARARGS}, +#endif {"seek", mmap_seek_method, METH_VARARGS}, {"seekable", mmap_seekable_method, METH_NOARGS}, {"size", mmap_size_method, METH_NOARGS},