[issue40915] multiple problems with mmap.resize() in Windows

Eryk Sun report at bugs.python.org
Tue Jun 9 22:26:33 EDT 2020


Eryk Sun <eryksun at gmail.com> added the comment:

For a concrete example, here's a rewrite of the Windows implementation that incorporates the suggested changes. 

#include <winternl.h>

#ifdef MS_WINDOWS
        /* a named file mapping that's open more than once can't be resized */
        /* this check could be moved into is_resizeable */
        if (self->tagname) {
            typedef NTSTATUS NTAPI ntqo_f(HANDLE, OBJECT_INFORMATION_CLASS,
                PVOID, ULONG, PULONG);
            ntqo_f *pNtQueryObject = (ntqo_f *)GetProcAddress(
                GetModuleHandleW(L"ntdll"), "NtQueryObject");
            if (pNtQueryObject) {
                PUBLIC_OBJECT_BASIC_INFORMATION info;
                NTSTATUS status = pNtQueryObject(self->map_handle,
                    ObjectBasicInformation, &info, sizeof(info), NULL);
                if (NT_SUCCESS(status) && info.HandleCount > 1) {
                    PyErr_SetFromWindowsErr(ERROR_USER_MAPPED_FILE);
                    return NULL;
                }
            }
        }
        DWORD error = 0;
        char *old_data = self->data;
        LARGE_INTEGER offset;
        offset.QuadPart = self->offset;
        /* close the file mapping */
        CloseHandle(self->map_handle);
        self->map_handle = NULL;
        /* if it's not the paging file, unmap the view and resize the file */
        if (self->file_handle != INVALID_HANDLE_VALUE) {
            UnmapViewOfFile(self->data);
            self->data = NULL;
            /* resize the file */
            if (!SetFilePointerEx(self->file_handle, offset, NULL,
                     FILE_BEGIN) ||
                !SetEndOfFile(self->file_handle)) {
                /* resizing failed. try to remap the file */
                error = GetLastError();
                new_size = self->size;
            }
        }
        /* create a new file mapping and map a new view */
        LARGE_INTEGER max_size;
        max_size.QuadPart = new_size;
        /* FIXME: call CreateFileMappingW with wchar_t tagname */
        self->map_handle = CreateFileMapping(self->file_handle, NULL,
            PAGE_READWRITE, max_size.HighPart, max_size.LowPart,
            self->tagname);
        if (self->map_handle != NULL &&
              GetLastError() != ERROR_ALREADY_EXISTS) {
            self->data = MapViewOfFile(self->map_handle, FILE_MAP_WRITE,
                offset.HighPart, offset.LowPart, new_size);
            if (self->data != NULL) {
                /* copy the old view if using the paging file */
                if (self->file_handle == INVALID_HANDLE_VALUE) {
                    memcpy(self->data, old_data,
                        self->size < new_size ? self->size : new_size);
                }
                self->size = new_size;
            } else {
                error = GetLastError();
                CloseHandle(self->map_handle);
                self->map_handle = NULL;
            }
        } else {
            error = GetLastError();
        }
        /* unmap the old view if using the paging file */
        if (self->file_handle == INVALID_HANDLE_VALUE) {
            UnmapViewOfFile(old_data);
        }
        if (error) {
            PyErr_SetFromWindowsErr(error);
            return NULL;
        }
        Py_RETURN_NONE;
#endif /* MS_WINDOWS */

----------

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue40915>
_______________________________________


More information about the Python-bugs-list mailing list