From 8c4563448c9c0c3519448f40ac238e12b8955f2d Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Tue, 2 Sep 2025 13:24:06 -0700 Subject: [PATCH] gh-87595: Support mmap.size() for anonymous mapping on Unix (GH-24781) Previously, the size would be returned on Windows and an OSError would be raised on Unix. Also, raise ValueError instead of OSError for trackfd=False. (cherry picked from commit 32032ee376fe20670e9a35e56beff48e59201261) Co-authored-by: Zackery Spytz Co-authored-by: Serhiy Storchaka --- Doc/library/mmap.rst | 4 ++++ Lib/test/test_mmap.py | 7 +++---- .../Library/2021-03-07-16-31-36.bpo-43429.Koa0mf.rst | 5 +++++ Modules/mmapmodule.c | 10 +++++++++- 4 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2021-03-07-16-31-36.bpo-43429.Koa0mf.rst diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst index 8fca79b23e4e15..5d81477443ca31 100644 --- a/Doc/library/mmap.rst +++ b/Doc/library/mmap.rst @@ -312,6 +312,10 @@ To map anonymous memory, -1 should be passed as the fileno along with the length Return the length of the file, which can be larger than the size of the memory-mapped area. + For anonymous mapping, return its size. + + .. versionchanged:: next + Supports anonymous mapping on Unix. .. method:: tell() diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py index a1cf5384ada5b5..81bf75014ea48f 100644 --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -5,7 +5,6 @@ from test.support.os_helper import TESTFN, unlink from test.support.script_helper import assert_python_ok import unittest -import errno import os import re import itertools @@ -281,9 +280,8 @@ def test_trackfd_parameter(self): if close_original_fd: f.close() self.assertEqual(len(m), size) - with self.assertRaises(OSError) as err_cm: + with self.assertRaises(ValueError): m.size() - self.assertEqual(err_cm.exception.errno, errno.EBADF) with self.assertRaises(ValueError): m.resize(size * 2) with self.assertRaises(ValueError): @@ -308,7 +306,7 @@ def test_trackfd_parameter(self): def test_trackfd_neg1(self): size = 64 with mmap.mmap(-1, size, trackfd=False) as m: - with self.assertRaises(OSError): + with self.assertRaises(ValueError): m.size() with self.assertRaises(ValueError): m.resize(size // 2) @@ -504,6 +502,7 @@ def test_anonymous(self): b = x & 0xff m[x] = b self.assertEqual(m[x], b) + self.assertEqual(m.size(), PAGESIZE) def test_read_all(self): m = mmap.mmap(-1, 16) diff --git a/Misc/NEWS.d/next/Library/2021-03-07-16-31-36.bpo-43429.Koa0mf.rst b/Misc/NEWS.d/next/Library/2021-03-07-16-31-36.bpo-43429.Koa0mf.rst new file mode 100644 index 00000000000000..a6221ba9c88585 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-03-07-16-31-36.bpo-43429.Koa0mf.rst @@ -0,0 +1,5 @@ +The :meth:`~mmap.mmap.size` method of the :class:`mmap.mmap` class now +returns the size of an anonymous mapping on both Unix and Windows. +Previously, the size would be returned on Windows and an :exc:`OSError` +would be raised on Unix. +Raise :exc:`ValueError` instead of :exc:`OSError` with ``trackfd=False``. diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index 4cc888004c3c27..0091bd93cc1bcc 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -728,7 +728,7 @@ mmap_size_method(mmap_object *self, #endif /* MS_WINDOWS */ #ifdef UNIX - { + if (self->fd != -1) { struct _Py_stat_struct status; if (_Py_fstat(self->fd, &status) == -1) return NULL; @@ -738,6 +738,14 @@ mmap_size_method(mmap_object *self, return PyLong_FromLong(status.st_size); #endif } + else if (self->trackfd) { + return PyLong_FromSsize_t(self->size); + } + else { + PyErr_SetString(PyExc_ValueError, + "can't get size with trackfd=False"); + return NULL; + } #endif /* UNIX */ }