Skip to content

Commit e7d4b2f

Browse files
authored
bpo-2122: Make mmap.flush() behave same on all platforms (GH-8692)
Previously, its behavior was platform-dependent and there was no error checking under Windows.
1 parent 28853a2 commit e7d4b2f

File tree

5 files changed

+36
-13
lines changed

5 files changed

+36
-13
lines changed

Doc/library/mmap.rst

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,13 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
191191
changes to the given range of bytes will be flushed to disk; otherwise, the
192192
whole extent of the mapping is flushed.
193193

194-
**(Windows version)** A nonzero value returned indicates success; zero
195-
indicates failure.
194+
``None`` is returned to indicate success. An exception is raised when the
195+
call failed.
196196

197-
**(Unix version)** A zero value is returned to indicate success. An
198-
exception is raised when the call failed.
197+
.. versionchanged:: 3.8
198+
Previously, a nonzero value was returned on success; zero was returned
199+
on error under Windows. A zero value was returned on success; an
200+
exception was raised on error under Unix.
199201

200202

201203
.. method:: move(dest, src, count)

Doc/whatsnew/3.8.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,13 @@ Changes in the Python API
265265
task name is visible in the ``repr()`` output of :class:`asyncio.Task` and
266266
can also be retrieved using the :meth:`~asyncio.Task.get_name` method.
267267

268+
* The :meth:`mmap.flush() <mmap.mmap.flush>` method now returns ``None`` on
269+
success and raises an exception on error under all platforms. Previously,
270+
its behavior was platform-depended: a nonzero value was returned on success;
271+
zero was returned on error under Windows. A zero value was returned on
272+
success; an exception was raised on error under Unix.
273+
(Contributed by Berker Peksag in :issue:`2122`.)
274+
268275

269276
CPython bytecode changes
270277
------------------------

Lib/test/test_mmap.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from test.support import (TESTFN, run_unittest, import_module, unlink,
1+
from test.support import (TESTFN, import_module, unlink,
22
requires, _2G, _4G, gc_collect, cpython_only)
33
import unittest
44
import os
@@ -741,6 +741,18 @@ def test_concat_repeat_exception(self):
741741
with self.assertRaises(TypeError):
742742
m * 2
743743

744+
def test_flush_return_value(self):
745+
# mm.flush() should return None on success, raise an
746+
# exception on error under all platforms.
747+
mm = mmap.mmap(-1, 16)
748+
self.addCleanup(mm.close)
749+
mm.write(b'python')
750+
result = mm.flush()
751+
self.assertIsNone(result)
752+
if os.name != 'nt':
753+
# 'offset' must be a multiple of mmap.PAGESIZE.
754+
self.assertRaises(OSError, mm.flush, 1, len(b'python'))
755+
744756

745757
class LargeMmapTests(unittest.TestCase):
746758

@@ -803,8 +815,5 @@ def test_around_4GB(self):
803815
self._test_around_boundary(_4G)
804816

805817

806-
def test_main():
807-
run_unittest(MmapTests, LargeMmapTests)
808-
809818
if __name__ == '__main__':
810-
test_main()
819+
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The :meth:`mmap.flush() <mmap.mmap.flush>` method now returns ``None`` on
2+
success, raises an exception on error under all platforms.

Modules/mmapmodule.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -569,18 +569,21 @@ mmap_flush_method(mmap_object *self, PyObject *args)
569569
}
570570

571571
if (self->access == ACCESS_READ || self->access == ACCESS_COPY)
572-
return PyLong_FromLong(0);
572+
Py_RETURN_NONE;
573573

574574
#ifdef MS_WINDOWS
575-
return PyLong_FromLong((long) FlushViewOfFile(self->data+offset, size));
575+
if (!FlushViewOfFile(self->data+offset, size)) {
576+
PyErr_SetFromWindowsErr(GetLastError());
577+
return NULL;
578+
}
579+
Py_RETURN_NONE;
576580
#elif defined(UNIX)
577-
/* XXX semantics of return value? */
578581
/* XXX flags for msync? */
579582
if (-1 == msync(self->data + offset, size, MS_SYNC)) {
580583
PyErr_SetFromErrno(PyExc_OSError);
581584
return NULL;
582585
}
583-
return PyLong_FromLong(0);
586+
Py_RETURN_NONE;
584587
#else
585588
PyErr_SetString(PyExc_ValueError, "flush not supported on this system");
586589
return NULL;

0 commit comments

Comments
 (0)