gh-127076: Ignore memory mmap in FileIO testing (#127088)

`mmap`, `munmap`, and `mprotect` are used by CPython for memory
management, which may occur in the middle of the FileIO tests. The
system calls can also be used with files, so `strace` includes them
in its `%file` and `%desc` filters.

Filter out the `mmap` system calls related to memory allocation for the
file tests. Currently FileIO doesn't do `mmap` at all, so didn't add
code to track from `mmap` through `munmap` since it wouldn't be used.
For now if an `mmap` on a fd happens, the call will be included (which
may cause test to fail), and at that time support for tracking the
address throug `munmap` could be added.
This commit is contained in:
Cody Maloney 2024-11-22 06:55:32 -08:00 committed by GitHub
parent 0a1944cda8
commit 46f8a7bbdb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 37 additions and 7 deletions

View File

@ -71,6 +71,27 @@ class StraceResult:
return sections
def _filter_memory_call(call):
# mmap can operate on a fd or "MAP_ANONYMOUS" which gives a block of memory.
# Ignore "MAP_ANONYMOUS + the "MAP_ANON" alias.
if call.syscall == "mmap" and "MAP_ANON" in call.args[3]:
return True
if call.syscall in ("munmap", "mprotect"):
return True
return False
def filter_memory(syscalls):
"""Filter out memory allocation calls from File I/O calls.
Some calls (mmap, munmap, etc) can be used on files or to just get a block
of memory. Use this function to filter out the memory related calls from
other calls."""
return [call for call in syscalls if not _filter_memory_call(call)]
@support.requires_subprocess()
def strace_python(code, strace_flags, check=True):
@ -93,8 +114,6 @@ def strace_python(code, strace_flags, check=True):
"-c",
textwrap.dedent(code),
__run_using_command=[_strace_binary] + strace_flags,
# Don't want to trace our JIT's own mmap and mprotect calls:
PYTHON_JIT="0",
)
except OSError as err:
return _make_error("Caught OSError", err)
@ -145,9 +164,14 @@ print("MARK __shutdown", flush=True)
return all_sections['code']
def get_syscalls(code, strace_flags, prelude="", cleanup=""):
def get_syscalls(code, strace_flags, prelude="", cleanup="",
ignore_memory=True):
"""Get the syscalls which a given chunk of python code generates"""
events = get_events(code, strace_flags, prelude=prelude, cleanup=cleanup)
if ignore_memory:
events = filter_memory(events)
return [ev.syscall for ev in events]
@ -177,5 +201,5 @@ def requires_strace():
return unittest.skipUnless(_can_strace(), "Requires working strace")
__all__ = ["get_events", "get_syscalls", "requires_strace", "strace_python",
"StraceEvent", "StraceResult"]
__all__ = ["filter_memory", "get_events", "get_syscalls", "requires_strace",
"strace_python", "StraceEvent", "StraceResult"]

View File

@ -364,8 +364,7 @@ class AutoFileTests:
@strace_helper.requires_strace()
def test_syscalls_read(self):
"""Check that the set of system calls produced by the I/O stack is what
is expected for various read cases.
"""Check set of system calls during common I/O patterns
It's expected as bits of the I/O implementation change, this will need
to change. The goal is to catch changes that unintentionally add
@ -383,6 +382,11 @@ class AutoFileTests:
prelude=prelude,
cleanup=cleanup)
# Some system calls (ex. mmap) can be used for both File I/O and
# memory allocation. Filter out the ones used for memory
# allocation.
syscalls = strace_helper.filter_memory(syscalls)
# The first call should be an open that returns a
# file descriptor (fd). Afer that calls may vary. Once the file
# is opened, check calls refer to it by fd as the filename

View File

@ -0,0 +1,2 @@
Filter out memory-related ``mmap``, ``munmap``, and ``mprotect`` calls from
file-related ones when testing :mod:`io` behavior using strace.