Skip to content

Implement Windows named mmap via CreateFileMappingW#7207

Merged
youknowone merged 1 commit intoRustPython:mainfrom
youknowone:win-mmap
Feb 23, 2026
Merged

Implement Windows named mmap via CreateFileMappingW#7207
youknowone merged 1 commit intoRustPython:mainfrom
youknowone:win-mmap

Conversation

@youknowone
Copy link
Member

@youknowone youknowone commented Feb 23, 2026

Use Win32 CreateFileMappingW + MapViewOfFile when tagname is provided, enabling inter-process shared memory for multiprocessing.heap.Arena. Anonymous mmaps without tagname still use memmap2.

Remove expectedFailure from test_tagname in test_mmap.py.

Summary by CodeRabbit

  • New Features
    • Windows: added support for named memory mappings so processes can create/open named shared memory via a tagname.
    • Named mappings behave like other mappings for read/write and flushing, include safe lifecycle handling, and are prevented from being resized to avoid unsafe operations.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

📝 Walkthrough

Walkthrough

This PR adds Windows named memory-mapping support: it exposes the Win32 System Memory feature in Cargo.toml and implements a Windows-only NamedMmap type plus associated code paths to create, map, access, flush, and drop named file mappings.

Changes

Cohort / File(s) Summary
Cargo Configuration
crates/stdlib/Cargo.toml
Added Windows feature Win32_System_Memory to enable Win32 memory APIs for named mapping support.
Windows Named Memory Mapping
crates/stdlib/src/mmap.rs
Added Windows-only NamedMmap struct (map handle, view pointer, len), Named variant to MmapObj, and tagname support in MmapNewArgs. Implemented creation via CreateFileMappingW/MapViewOfFile, accessors (as_slice/as_bytes_mut), Drop/unmap/close, flush via FlushViewOfFile, guards to prevent resizing named maps, and adjusted read/write/resize/flush flows to route through NamedMmap on Windows.

Sequence Diagram(s)

sequenceDiagram
    participant Python as "Python user"
    participant PyMmap as "PyMmap"
    participant Validator as "Tagname validator"
    participant Win32 as "Win32 APIs"
    participant Kernel as "Kernel memory"

    Python->>PyMmap: py_new(..., tagname="name")
    PyMmap->>Validator: validate/convert tagname
    Validator-->>PyMmap: validated tagname
    PyMmap->>Win32: CreateFileMappingW(..., name)
    Win32->>Kernel: allocate/identify named mapping
    Kernel-->>Win32: map_handle
    Win32-->>PyMmap: map_handle
    PyMmap->>Win32: MapViewOfFile(map_handle, access)
    Win32->>Kernel: map view into process
    Kernel-->>Win32: view_ptr
    Win32-->>PyMmap: view_ptr
    PyMmap->>PyMmap: store NamedMmap(map_handle, view_ptr, len)
    PyMmap-->>Python: return MmapObj::Named
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • mmap for windows #6329: Prior Windows mmap implementation changes that this PR extends with named-mmap and tagname support.

Poem

🐰 I found a tagname, snug and sweet,
I mapped its memory, soft and neat,
Handles held, views hugged tight,
Shared bytes hopping into sight —
A tiny rabbit cheers this Windows feat!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Implement Windows named mmap via CreateFileMappingW' directly and clearly summarizes the main change: adding Windows named memory mapping support using the CreateFileMappingW API, which aligns with the substantial modifications to crates/stdlib/src/mmap.rs and PR objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

Code has been automatically formatted

The code in this PR has been formatted using:

  • cargo fmt --all
    Please pull the latest changes before pushing again:
git pull origin win-mmap

@github-actions
Copy link
Contributor

github-actions bot commented Feb 23, 2026

📦 Library Dependencies

The following Lib/ modules were modified. Here are their dependencies:

[ ] test: cpython/Lib/test/test_mmap.py (TODO: 2)

dependencies:

dependent tests: (no tests depend on mmap)

Legend:

  • [+] path exists in CPython
  • [x] up-to-date, [ ] outdated

@youknowone youknowone marked this pull request as ready for review February 23, 2026 13:09
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/stdlib/src/mmap.rs (1)

1190-1219: ⚠️ Potential issue | 🔴 Critical

resize silently converts a Named mmap into an anonymous one.

For Named mmaps, self.handle is INVALID_HANDLE_VALUE, so is_anonymous is true. The anonymous resize path creates a new MmapMut via map_anon() and replaces the Named variant with MmapObj::Write. This silently destroys the named shared memory mapping — any other process sharing the tagname will no longer see updates, and the mapping loses its named identity.

At minimum, Named mmaps should be detected and an error raised (similar to how the Unix path returns an error for missing mremap). Better yet, the named mapping should be re-created with CreateFileMappingW + MapViewOfFile at the new size.

Proposed minimal fix: reject resize for Named mmaps
         // Get the lock on mmap
         let mut mmap_guard = self.mmap.lock();

+        // Named mmaps cannot be resized via the anonymous path
+        if let Some(MmapObj::Named(_)) = mmap_guard.as_ref() {
+            return Err(vm.new_system_error(
+                "mmap: resizing named memory mappings is not supported",
+            ));
+        }
+
         if is_anonymous {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/stdlib/src/mmap.rs` around lines 1190 - 1219, The resize
implementation silently converts Named mappings into anonymous ones by checking
is_anonymous via self.handle and then unconditionally calling map_anon() and
assigning MmapObj::Write; instead detect Named mappings in resize (use
self.handle, MmapObj variants and mmap.lock()/mmap_guard) and return an error
when attempting to resize a Named mmap (mirror the Unix behavior for missing
mremap) OR implement re-creation via Windows APIs (CreateFileMappingW +
MapViewOfFile) to preserve the named mapping; update the code path that
currently calls MmapOptions::map_anon() so it either raises a clear error for
Named maps or uses the CreateFileMappingW/MapViewOfFile flow to create a new
named mapping and copy data before replacing mmap_guard and updating self.size.
🧹 Nitpick comments (1)
crates/stdlib/src/mmap.rs (1)

849-861: as_bytes_mut returns a mutable slice for Named regardless of access mode.

Unlike MmapObj::Read which panics, the Named arm always returns a mutable slice. While current callers (try_writable, buffer protocol) check access mode before reaching this point, adding a debug assertion would strengthen the invariant:

                 #[cfg(windows)]
-                MmapObj::Named(named) => unsafe {
-                    core::slice::from_raw_parts_mut(named.view_ptr, named.len)
-                },
+                MmapObj::Named(named) => {
+                    debug_assert!(
+                        !matches!(self.access, AccessMode::Read),
+                        "mmap can't modify a readonly memory map."
+                    );
+                    unsafe { core::slice::from_raw_parts_mut(named.view_ptr, named.len) }
+                }

Note: self is not directly accessible in as_bytes_mut since it operates on the MmapObj match. If restructuring isn't feasible, adding a comment documenting the caller-enforced invariant would suffice.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/stdlib/src/mmap.rs` around lines 849 - 861, The as_bytes_mut method
currently returns a mutable slice for MmapObj::Named regardless of access mode;
update as_bytes_mut (the match arm for MmapObj::Named) to either add a debug
assertion that the named mapping is writable (assert the Named object's
access/flags indicate writable access) or, if that field isn't accessible here,
add a clear comment above the method and the MmapObj::Named arm documenting the
caller-enforced invariant (try_writable and buffer protocol callers must have
verified writability) so future readers/maintainers know why a mutable slice is
returned despite no runtime check; reference as_bytes_mut, MmapObj::Named,
MmapObj::Read, try_writable and the buffer protocol in the comment or assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/stdlib/src/mmap.rs`:
- Around line 1016-1019: The comment is wrong: MmapObj::Named can be file-backed
and thus may need flushing; update the flush handling for the Windows Named
variant in the flush implementation to either detect whether the Named mapping
was created from a real file handle (file-backed) and call FlushViewOfFile only
for those, or simply call FlushViewOfFile unconditionally for MmapObj::Named.
Locate the Windows branch handling MmapObj::Named in the flush function and
replace the no-op with a call to the appropriate Windows flush routine
(FlushViewOfFile) or conditional logic based on how the Named mapping was
constructed.
- Around line 671-680: The current logic closes duplicated_handle and leaves
self.handle as INVALID_HANDLE_VALUE for file-backed named mappings (code around
duplicated_handle, fh and CreateFileMappingW), which changes behavior of size()
and resize(); either preserve the duplicated handle in self.handle or document
the intentional divergence. Fix by not closing duplicated_handle when fh is Some
and tagname is used: keep duplicated_handle open and assign it to self.handle
after successful CreateFileMappingW (ensure you only close duplicated_handle on
error or when the mmap is dropped), update the cleanup paths to avoid
double-closing, and add a short comment near the
duplicated_handle/fh/CreateFileMappingW block explaining why the duplicated OS
file handle is retained in self.handle so size() and resize() continue to
operate on the file-backed mapping.
- Around line 663-728: The code computes total_size = (offset as u64) +
(map_size as u64) without overflow checks in the tagged-path; change this to use
checked_add like the non-tagged path (use offset as u64 .checked_add(map_size as
u64)) and on None return the same kind of error (e.g., return
Err(io::Error::new(...).to_pyexception(vm))) before calling CreateFileMappingW
so CreateFileMappingW and subsequent logic (CreateFileMappingW, MapViewOfFile,
NamedMmap construction) only run with a validated, non-overflowing size.

---

Outside diff comments:
In `@crates/stdlib/src/mmap.rs`:
- Around line 1190-1219: The resize implementation silently converts Named
mappings into anonymous ones by checking is_anonymous via self.handle and then
unconditionally calling map_anon() and assigning MmapObj::Write; instead detect
Named mappings in resize (use self.handle, MmapObj variants and
mmap.lock()/mmap_guard) and return an error when attempting to resize a Named
mmap (mirror the Unix behavior for missing mremap) OR implement re-creation via
Windows APIs (CreateFileMappingW + MapViewOfFile) to preserve the named mapping;
update the code path that currently calls MmapOptions::map_anon() so it either
raises a clear error for Named maps or uses the CreateFileMappingW/MapViewOfFile
flow to create a new named mapping and copy data before replacing mmap_guard and
updating self.size.

---

Nitpick comments:
In `@crates/stdlib/src/mmap.rs`:
- Around line 849-861: The as_bytes_mut method currently returns a mutable slice
for MmapObj::Named regardless of access mode; update as_bytes_mut (the match arm
for MmapObj::Named) to either add a debug assertion that the named mapping is
writable (assert the Named object's access/flags indicate writable access) or,
if that field isn't accessible here, add a clear comment above the method and
the MmapObj::Named arm documenting the caller-enforced invariant (try_writable
and buffer protocol callers must have verified writability) so future
readers/maintainers know why a mutable slice is returned despite no runtime
check; reference as_bytes_mut, MmapObj::Named, MmapObj::Read, try_writable and
the buffer protocol in the comment or assertion.

ℹ️ Review info

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f096bb7 and 0cdce3a.

⛔ Files ignored due to path filters (1)
  • Lib/test/test_mmap.py is excluded by !Lib/**
📒 Files selected for processing (2)
  • crates/stdlib/Cargo.toml
  • crates/stdlib/src/mmap.rs

Comment on lines +671 to +680
let fh = if let Some(fh) = fh {
// Close the duplicated handle - we'll use the original
// file handle for CreateFileMappingW
if duplicated_handle != INVALID_HANDLE_VALUE {
unsafe { CloseHandle(duplicated_handle) };
}
fh
} else {
INVALID_HANDLE_VALUE
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Closing the duplicated handle when using tagname with a file-backed mapping — verify this is intentional.

When a file handle is provided alongside a tagname, the duplicated handle is closed and the original fh (from get_osfhandle) is passed to CreateFileMappingW. After CreateFileMappingW succeeds, the mapping object is independent of the file handle, so this is technically correct. However, this diverges from the non-tagged path (which keeps the duplicated handle) and means self.handle is INVALID_HANDLE_VALUE for file-backed named mmaps. This affects size() (returns map size instead of file size) and resize() (treats it as anonymous).

Consider storing the duplicated handle in self.handle for file-backed named mmaps, or at minimum add a comment explaining why this is intentional.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/stdlib/src/mmap.rs` around lines 671 - 680, The current logic closes
duplicated_handle and leaves self.handle as INVALID_HANDLE_VALUE for file-backed
named mappings (code around duplicated_handle, fh and CreateFileMappingW), which
changes behavior of size() and resize(); either preserve the duplicated handle
in self.handle or document the intentional divergence. Fix by not closing
duplicated_handle when fh is Some and tagname is used: keep duplicated_handle
open and assign it to self.handle after successful CreateFileMappingW (ensure
you only close duplicated_handle on error or when the mmap is dropped), update
the cleanup paths to avoid double-closing, and add a short comment near the
duplicated_handle/fh/CreateFileMappingW block explaining why the duplicated OS
file handle is retained in self.handle so size() and resize() continue to
operate on the file-backed mapping.

Use Win32 CreateFileMappingW + MapViewOfFile when tagname is
provided, enabling inter-process shared memory for
multiprocessing.heap.Arena. Anonymous mmaps without tagname
still use memmap2.

Remove expectedFailure from test_tagname in test_mmap.py.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
crates/stdlib/src/mmap.rs (1)

671-680: ⚠️ Potential issue | 🟠 Major

File-backed named mappings lose the OS file handle — size() won't return the file size.

When a tagname is provided alongside a real file handle, the duplicated handle is closed and self.handle is set to INVALID_HANDLE_VALUE. This causes size() (line 1331) to return self.__len__() (the mapping length) instead of querying the actual file size via GetFileSize. CPython's mmap.size() returns the file size for file-backed mappings.

Consider storing duplicated_handle in self.handle for file-backed named mmaps instead of closing it, or add a comment explaining the intentional divergence from CPython behavior.

Also applies to: 720-729

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/stdlib/src/mmap.rs` around lines 671 - 680, The code closes
duplicated_handle and leaves self.handle as INVALID_HANDLE_VALUE for file-backed
named mappings, causing size() to fall back to the mapping length instead of
using GetFileSize; change the logic in the block that currently returns
fh/INVALID_HANDLE_VALUE (the code handling fh and duplicated_handle) so that for
file-backed named mmaps you keep the duplicated_handle (assign duplicated_handle
to self.handle) instead of closing it, and only close the original
duplicated_handle when it is truly unused; ensure the new ownership is
consistent with the destructor/cleanup so no handle is leaked and size() can
call GetFileSize on self.handle.
🧹 Nitpick comments (1)
crates/stdlib/src/mmap.rs (1)

851-863: as_bytes_mut doesn't guard against Read-mode Named mappings.

MmapObj::Read panics here (line 854), but a Named mmap created with AccessMode::Read (FILE_MAP_READ) will silently return a mutable slice. Writing to that memory would cause an OS-level access violation. While callers currently check access mode upstream, adding a consistent guard here would be safer.

🛡️ Suggested defensive guard
                    #[cfg(windows)]
                    MmapObj::Named(named) => unsafe {
+                       debug_assert!(
+                           !matches!(
+                               *m.as_ref().unwrap(),
+                               MmapObj::Named(_) if false // access check is on PyMmap, not MmapObj
+                           )
+                       );
                        core::slice::from_raw_parts_mut(named.view_ptr, named.len)
                    },

Actually, since as_bytes_mut doesn't have access to self.access, a simpler approach: document that callers must check access mode, mirroring the MmapObj::Read panic's implicit contract.

Alternatively, pass access into the function or move the check to the match:

 fn as_bytes_mut(&self) -> BorrowedValueMut<'_, [u8]> {
+    assert!(
+        self.access != AccessMode::Read,
+        "mmap can't modify a readonly memory map."
+    );
     PyMutexGuard::map(self.mmap.lock(), |m| {
         match m.as_mut().expect("mmap closed or invalid") {
             MmapObj::Read(_) => panic!("mmap can't modify a readonly memory map."),
             MmapObj::Write(mmap) => &mut mmap[..],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/stdlib/src/mmap.rs` around lines 851 - 863, as_bytes_mut currently
returns a mutable slice for MmapObj::Named even if that named mapping was opened
read-only, which can lead to an access violation; update as_bytes_mut (or its
caller) to check the mapping's access mode and refuse/mirror the MmapObj::Read
behavior for read-only Named maps: either accept and use an access parameter in
as_bytes_mut and panic when access == AccessMode::Read for MmapObj::Named, or
add a guard in the match arm for MmapObj::Named that inspects the named
mapping's access flag and panics if it's read-only, ensuring Named maps opened
with AccessMode::Read are not exposed as mutable slices.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/stdlib/src/mmap.rs`:
- Around line 227-243: The Drop impl for NamedMmap uses .is_null() on map_handle
which is an isize (windows-sys HANDLE) and doesn't have that method; change the
checks that call self.map_handle.is_null() to integer comparisons (e.g.
self.map_handle != 0 or self.map_handle == 0) while leaving pointer checks like
self.view_ptr.is_null() as-is; update the Drop impl (and any other places using
map_handle.is_null(), e.g. the other occurrence noted) to use map_handle != 0
before calling CloseHandle.

---

Duplicate comments:
In `@crates/stdlib/src/mmap.rs`:
- Around line 671-680: The code closes duplicated_handle and leaves self.handle
as INVALID_HANDLE_VALUE for file-backed named mappings, causing size() to fall
back to the mapping length instead of using GetFileSize; change the logic in the
block that currently returns fh/INVALID_HANDLE_VALUE (the code handling fh and
duplicated_handle) so that for file-backed named mmaps you keep the
duplicated_handle (assign duplicated_handle to self.handle) instead of closing
it, and only close the original duplicated_handle when it is truly unused;
ensure the new ownership is consistent with the destructor/cleanup so no handle
is leaked and size() can call GetFileSize on self.handle.

---

Nitpick comments:
In `@crates/stdlib/src/mmap.rs`:
- Around line 851-863: as_bytes_mut currently returns a mutable slice for
MmapObj::Named even if that named mapping was opened read-only, which can lead
to an access violation; update as_bytes_mut (or its caller) to check the
mapping's access mode and refuse/mirror the MmapObj::Read behavior for read-only
Named maps: either accept and use an access parameter in as_bytes_mut and panic
when access == AccessMode::Read for MmapObj::Named, or add a guard in the match
arm for MmapObj::Named that inspects the named mapping's access flag and panics
if it's read-only, ensuring Named maps opened with AccessMode::Read are not
exposed as mutable slices.

ℹ️ Review info

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0cdce3a and 399f67f.

⛔ Files ignored due to path filters (1)
  • Lib/test/test_mmap.py is excluded by !Lib/**
📒 Files selected for processing (2)
  • crates/stdlib/Cargo.toml
  • crates/stdlib/src/mmap.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/stdlib/Cargo.toml

Comment on lines +227 to +243
#[cfg(windows)]
impl Drop for NamedMmap {
fn drop(&mut self) {
unsafe {
if !self.view_ptr.is_null() {
UnmapViewOfFile(
windows_sys::Win32::System::Memory::MEMORY_MAPPED_VIEW_ADDRESS {
Value: self.view_ptr as *mut _,
},
);
}
if !self.map_handle.is_null() {
CloseHandle(self.map_handle);
}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify that HANDLE is indeed `isize` in the windows_sys version used by this repo
echo "=== Checking windows_sys HANDLE definition ==="
rg -n 'type HANDLE' --type rust -g '!target/**' 2>/dev/null | head -20

echo ""
echo "=== Checking all .is_null() calls on HANDLE-typed variables in mmap.rs ==="
rg -n '\.is_null\(\)' crates/stdlib/src/mmap.rs

echo ""
echo "=== Checking the exact context of line 238 and 700 in mmap.rs ==="
sed -n '235,245p' crates/stdlib/src/mmap.rs
echo "---"
sed -n '698,708p' crates/stdlib/src/mmap.rs

echo ""
echo "=== Checking windows_sys version in Cargo.lock ==="
rg -A2 'name = "windows-sys"' Cargo.lock | head -10

Repository: RustPython/RustPython

Length of output: 1478


🏁 Script executed:

#!/bin/bash
# Find HANDLE imports and usage in mmap.rs
echo "=== Finding HANDLE imports in mmap.rs ==="
head -100 crates/stdlib/src/mmap.rs | grep -E 'use.*HANDLE|use.*windows'

echo ""
echo "=== Checking struct definitions with HANDLE in mmap.rs ==="
rg -n 'HANDLE' crates/stdlib/src/mmap.rs | head -30

echo ""
echo "=== Checking the actual HANDLE type in windows-sys ==="
# Try to find what HANDLE resolves to by checking the windows-sys documentation or source
# windows_sys defines HANDLE as isize in most versions, but let's verify
python3 << 'EOF'
# Check windows-sys version info
import subprocess
result = subprocess.run(['rg', 'windows-sys', 'Cargo.toml'], capture_output=True, text=True)
print("=== windows-sys in Cargo.toml ===")
print(result.stdout)
EOF

Repository: RustPython/RustPython

Length of output: 2360


🏁 Script executed:

#!/bin/bash
# Verify the HANDLE type definition in windows-sys 0.61.2
echo "=== Checking if code compiles (attempting cargo check on mmap.rs) ==="
cd crates/stdlib && cargo check --message-format=short 2>&1 | grep -A3 -B1 'mmap\|is_null' | head -40

echo ""
echo "=== Confirming HANDLE comparison patterns in file ==="
rg -n 'INVALID_HANDLE_VALUE as isize' crates/stdlib/src/mmap.rs | head -10

Repository: RustPython/RustPython

Length of output: 151


HANDLE is isize in windows-sys — .is_null() method does not exist on integer types and will fail to compile.

In windows-sys, HANDLE is defined as isize. The .is_null() method is only available on raw pointer types (*const T, *mut T), not on integer types. Lines 238 and 700 (map_handle.is_null() and if !self.map_handle.is_null()) will both produce error[E0599]: no method named is_null found for type isize.

The correct pattern is used elsewhere in the file (e.g., lines 296, 577, 674): compare directly using != or == operators.

Proposed fix

Drop impl at line 238:

-                if !self.map_handle.is_null() {
+                if self.map_handle != 0 {

And at line 700:

-                if map_handle.is_null() {
+                if map_handle != 0 {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#[cfg(windows)]
impl Drop for NamedMmap {
fn drop(&mut self) {
unsafe {
if !self.view_ptr.is_null() {
UnmapViewOfFile(
windows_sys::Win32::System::Memory::MEMORY_MAPPED_VIEW_ADDRESS {
Value: self.view_ptr as *mut _,
},
);
}
if !self.map_handle.is_null() {
CloseHandle(self.map_handle);
}
}
}
}
#[cfg(windows)]
impl Drop for NamedMmap {
fn drop(&mut self) {
unsafe {
if !self.view_ptr.is_null() {
UnmapViewOfFile(
windows_sys::Win32::System::Memory::MEMORY_MAPPED_VIEW_ADDRESS {
Value: self.view_ptr as *mut _,
},
);
}
if self.map_handle != 0 {
CloseHandle(self.map_handle);
}
}
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/stdlib/src/mmap.rs` around lines 227 - 243, The Drop impl for
NamedMmap uses .is_null() on map_handle which is an isize (windows-sys HANDLE)
and doesn't have that method; change the checks that call
self.map_handle.is_null() to integer comparisons (e.g. self.map_handle != 0 or
self.map_handle == 0) while leaving pointer checks like self.view_ptr.is_null()
as-is; update the Drop impl (and any other places using map_handle.is_null(),
e.g. the other occurrence noted) to use map_handle != 0 before calling
CloseHandle.

@youknowone youknowone merged commit 490a17f into RustPython:main Feb 23, 2026
14 checks passed
@youknowone youknowone deleted the win-mmap branch February 23, 2026 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant