Commit e895de3e authored by Davin Potts's avatar Davin Potts Committed by GitHub

bpo-35813: Tests and docs for shared_memory (#11816)

* Added tests for shared_memory submodule.

* Added tests for ShareableList.

* Fix bug in allocationn size during creation of empty ShareableList illuminated by existing test run on Linux.

* Initial set of docs for shared_memory module.

* Added docs for ShareableList, added doctree entry for shared_memory submodule, name refactoring for greater clarity.

* Added examples to SharedMemoryManager docs, for ease of documentation switched away from exclusively registered functions to some explicit methods on SharedMemoryManager.

* Wording tweaks to docs.

* Fix test failures on Windows.

* Added tests around SharedMemoryManager.

* Documentation tweaks.

* Fix inappropriate test on Windows.

* Further documentation tweaks.

* Fix bare exception.

* Removed __copyright__.

* Fixed typo in doc, removed comment.

* Updated SharedMemoryManager preliminary tests to reflect change of not supporting all registered functions on SyncManager.

* Added Sphinx doctest run controls.

* CloseHandle should be in a finally block in case MapViewOfFile fails.

* Missed opportunity to use with statement.

* Switch to self.addCleanup to spare long try/finally blocks and save one indentation, change to use decorator to skip test instead.

* Simplify the posixshmem extension module.

Provide shm_open() and shm_unlink() functions.  Move other
functionality into the shared_memory.py module.

* Added to doc around size parameter of SharedMemory.

* Changed PosixSharedMemory.size to use os.fstat.

* Change SharedMemory.buf to a read-only property as well as NamedSharedMemory.size.

* Marked as provisional per PEP411 in docstring.

* Changed SharedMemoryTracker to be private.

* Removed registered Proxy Objects from SharedMemoryManager.

* Removed shareable_wrap().

* Removed shareable_wrap() and dangling references to it.

* For consistency added __reduce__ to key classes.

* Fix for potential race condition on Windows for O_CREX.

* Remove unused imports.

* Update access to kernel32 on Windows per feedback from eryksun.

* Moved kernel32 calls to _winapi.

* Removed ShareableList.copy as redundant.

* Changes to _winapi use from eryksun feedback.

* Adopt simpler SharedMemory API, collapsing PosixSharedMemory and WindowsNamedSharedMemory into one.

* Fix missing docstring on class, add test for ignoring size when attaching.

* Moved SharedMemoryManager to managers module, tweak to fragile test.

* Tweak to exception in OpenFileMapping suggested by eryksun.

* Mark a few dangling bits as private as suggested by Giampaolo.
parent d610116a
......@@ -15,6 +15,7 @@ multitasking). Here's an overview:
threading.rst
multiprocessing.rst
multiprocessing.shared_memory.rst
concurrent.rst
concurrent.futures.rst
subprocess.rst
......
This diff is collapsed.
#
# Module providing the `SyncManager` class for dealing
# Module providing manager classes for dealing
# with shared objects
#
# multiprocessing/managers.py
......@@ -8,7 +8,8 @@
# Licensed to PSF under a Contributor Agreement.
#
__all__ = [ 'BaseManager', 'SyncManager', 'BaseProxy', 'Token' ]
__all__ = [ 'BaseManager', 'SyncManager', 'BaseProxy', 'Token',
'SharedMemoryManager' ]
#
# Imports
......@@ -19,6 +20,7 @@ import threading
import array
import queue
import time
from os import getpid
from traceback import format_exc
......@@ -28,6 +30,11 @@ from . import pool
from . import process
from . import util
from . import get_context
try:
from . import shared_memory
HAS_SHMEM = True
except ImportError:
HAS_SHMEM = False
#
# Register some things for pickling
......@@ -1200,3 +1207,143 @@ SyncManager.register('Namespace', Namespace, NamespaceProxy)
# types returned by methods of PoolProxy
SyncManager.register('Iterator', proxytype=IteratorProxy, create_method=False)
SyncManager.register('AsyncResult', create_method=False)
#
# Definition of SharedMemoryManager and SharedMemoryServer
#
if HAS_SHMEM:
class _SharedMemoryTracker:
"Manages one or more shared memory segments."
def __init__(self, name, segment_names=[]):
self.shared_memory_context_name = name
self.segment_names = segment_names
def register_segment(self, segment_name):
"Adds the supplied shared memory block name to tracker."
util.debug(f"Register segment {segment_name!r} in pid {getpid()}")
self.segment_names.append(segment_name)
def destroy_segment(self, segment_name):
"""Calls unlink() on the shared memory block with the supplied name
and removes it from the list of blocks being tracked."""
util.debug(f"Destroy segment {segment_name!r} in pid {getpid()}")
self.segment_names.remove(segment_name)
segment = shared_memory.SharedMemory(segment_name)
segment.close()
segment.unlink()
def unlink(self):
"Calls destroy_segment() on all tracked shared memory blocks."
for segment_name in self.segment_names[:]:
self.destroy_segment(segment_name)
def __del__(self):
util.debug(f"Call {self.__class__.__name__}.__del__ in {getpid()}")
self.unlink()
def __getstate__(self):
return (self.shared_memory_context_name, self.segment_names)
def __setstate__(self, state):
self.__init__(*state)
class SharedMemoryServer(Server):
public = Server.public + \
['track_segment', 'release_segment', 'list_segments']
def __init__(self, *args, **kwargs):
Server.__init__(self, *args, **kwargs)
self.shared_memory_context = \
_SharedMemoryTracker(f"shmm_{self.address}_{getpid()}")
util.debug(f"SharedMemoryServer started by pid {getpid()}")
def create(self, c, typeid, *args, **kwargs):
"""Create a new distributed-shared object (not backed by a shared
memory block) and return its id to be used in a Proxy Object."""
# Unless set up as a shared proxy, don't make shared_memory_context
# a standard part of kwargs. This makes things easier for supplying
# simple functions.
if hasattr(self.registry[typeid][-1], "_shared_memory_proxy"):
kwargs['shared_memory_context'] = self.shared_memory_context
return Server.create(self, c, typeid, *args, **kwargs)
def shutdown(self, c):
"Call unlink() on all tracked shared memory, terminate the Server."
self.shared_memory_context.unlink()
return Server.shutdown(self, c)
def track_segment(self, c, segment_name):
"Adds the supplied shared memory block name to Server's tracker."
self.shared_memory_context.register_segment(segment_name)
def release_segment(self, c, segment_name):
"""Calls unlink() on the shared memory block with the supplied name
and removes it from the tracker instance inside the Server."""
self.shared_memory_context.destroy_segment(segment_name)
def list_segments(self, c):
"""Returns a list of names of shared memory blocks that the Server
is currently tracking."""
return self.shared_memory_context.segment_names
class SharedMemoryManager(BaseManager):
"""Like SyncManager but uses SharedMemoryServer instead of Server.
It provides methods for creating and returning SharedMemory instances
and for creating a list-like object (ShareableList) backed by shared
memory. It also provides methods that create and return Proxy Objects
that support synchronization across processes (i.e. multi-process-safe
locks and semaphores).
"""
_Server = SharedMemoryServer
def __init__(self, *args, **kwargs):
BaseManager.__init__(self, *args, **kwargs)
util.debug(f"{self.__class__.__name__} created by pid {getpid()}")
def __del__(self):
util.debug(f"{self.__class__.__name__}.__del__ by pid {getpid()}")
pass
def get_server(self):
'Better than monkeypatching for now; merge into Server ultimately'
if self._state.value != State.INITIAL:
if self._state.value == State.STARTED:
raise ProcessError("Already started SharedMemoryServer")
elif self._state.value == State.SHUTDOWN:
raise ProcessError("SharedMemoryManager has shut down")
else:
raise ProcessError(
"Unknown state {!r}".format(self._state.value))
return self._Server(self._registry, self._address,
self._authkey, self._serializer)
def SharedMemory(self, size):
"""Returns a new SharedMemory instance with the specified size in
bytes, to be tracked by the manager."""
with self._Client(self._address, authkey=self._authkey) as conn:
sms = shared_memory.SharedMemory(None, create=True, size=size)
try:
dispatch(conn, None, 'track_segment', (sms.name,))
except BaseException as e:
sms.unlink()
raise e
return sms
def ShareableList(self, sequence):
"""Returns a new ShareableList instance populated with the values
from the input sequence, to be tracked by the manager."""
with self._Client(self._address, authkey=self._authkey) as conn:
sl = shared_memory.ShareableList(sequence)
try:
dispatch(conn, None, 'track_segment', (sl.shm.name,))
except BaseException as e:
sl.shm.unlink()
raise e
return sl
This diff is collapsed.
This diff is collapsed.
/*[clinic input]
preserve
[clinic start generated code]*/
#if defined(HAVE_SHM_OPEN)
PyDoc_STRVAR(_posixshmem_shm_open__doc__,
"shm_open($module, /, path, flags, mode=511)\n"
"--\n"
"\n"
"Open a shared memory object. Returns a file descriptor (integer).");
#define _POSIXSHMEM_SHM_OPEN_METHODDEF \
{"shm_open", (PyCFunction)(void(*)(void))_posixshmem_shm_open, METH_FASTCALL|METH_KEYWORDS, _posixshmem_shm_open__doc__},
static int
_posixshmem_shm_open_impl(PyObject *module, PyObject *path, int flags,
int mode);
static PyObject *
_posixshmem_shm_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"path", "flags", "mode", NULL};
static _PyArg_Parser _parser = {"Ui|i:shm_open", _keywords, 0};
PyObject *path;
int flags;
int mode = 511;
int _return_value;
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&path, &flags, &mode)) {
goto exit;
}
_return_value = _posixshmem_shm_open_impl(module, path, flags, mode);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyLong_FromLong((long)_return_value);
exit:
return return_value;
}
#endif /* defined(HAVE_SHM_OPEN) */
#if defined(HAVE_SHM_UNLINK)
PyDoc_STRVAR(_posixshmem_shm_unlink__doc__,
"shm_unlink($module, /, path)\n"
"--\n"
"\n"
"Remove a shared memory object (similar to unlink()).\n"
"\n"
"Remove a shared memory object name, and, once all processes have unmapped\n"
"the object, de-allocates and destroys the contents of the associated memory\n"
"region.");
#define _POSIXSHMEM_SHM_UNLINK_METHODDEF \
{"shm_unlink", (PyCFunction)(void(*)(void))_posixshmem_shm_unlink, METH_FASTCALL|METH_KEYWORDS, _posixshmem_shm_unlink__doc__},
static PyObject *
_posixshmem_shm_unlink_impl(PyObject *module, PyObject *path);
static PyObject *
_posixshmem_shm_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"path", NULL};
static _PyArg_Parser _parser = {"U:shm_unlink", _keywords, 0};
PyObject *path;
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&path)) {
goto exit;
}
return_value = _posixshmem_shm_unlink_impl(module, path);
exit:
return return_value;
}
#endif /* defined(HAVE_SHM_UNLINK) */
#ifndef _POSIXSHMEM_SHM_OPEN_METHODDEF
#define _POSIXSHMEM_SHM_OPEN_METHODDEF
#endif /* !defined(_POSIXSHMEM_SHM_OPEN_METHODDEF) */
#ifndef _POSIXSHMEM_SHM_UNLINK_METHODDEF
#define _POSIXSHMEM_SHM_UNLINK_METHODDEF
#endif /* !defined(_POSIXSHMEM_SHM_UNLINK_METHODDEF) */
/*[clinic end generated code: output=ff9cf0bc9b8baddf input=a9049054013a1b77]*/
This diff is collapsed.
......@@ -159,6 +159,7 @@ def create_converter(type_, format_unit):
create_converter('HANDLE', '" F_HANDLE "')
create_converter('HMODULE', '" F_HANDLE "')
create_converter('LPSECURITY_ATTRIBUTES', '" F_POINTER "')
create_converter('LPCVOID', '" F_POINTER "')
create_converter('BOOL', 'i') # F_BOOL used previously (always 'i')
create_converter('DWORD', 'k') # F_DWORD is always "k" (which is much shorter)
......@@ -186,8 +187,17 @@ class DWORD_return_converter(CReturnConverter):
self.err_occurred_if("_return_value == PY_DWORD_MAX", data)
data.return_conversion.append(
'return_value = Py_BuildValue("k", _return_value);\n')
class LPVOID_return_converter(CReturnConverter):
type = 'LPVOID'
def render(self, function, data):
self.declare(data)
self.err_occurred_if("_return_value == NULL", data)
data.return_conversion.append(
'return_value = HANDLE_TO_PYNUM(_return_value);\n')
[python start generated code]*/
/*[python end generated code: output=da39a3ee5e6b4b0d input=27456f8555228b62]*/
/*[python end generated code: output=da39a3ee5e6b4b0d input=79464c61a31ae932]*/
#include "clinic/_winapi.c.h"
......@@ -464,6 +474,41 @@ _winapi_CreateFile_impl(PyObject *module, LPCTSTR file_name,
return handle;
}
/*[clinic input]
_winapi.CreateFileMapping -> HANDLE
file_handle: HANDLE
security_attributes: LPSECURITY_ATTRIBUTES
protect: DWORD
max_size_high: DWORD
max_size_low: DWORD
name: LPCWSTR
/
[clinic start generated code]*/
static HANDLE
_winapi_CreateFileMapping_impl(PyObject *module, HANDLE file_handle,
LPSECURITY_ATTRIBUTES security_attributes,
DWORD protect, DWORD max_size_high,
DWORD max_size_low, LPCWSTR name)
/*[clinic end generated code: output=6c0a4d5cf7f6fcc6 input=3dc5cf762a74dee8]*/
{
HANDLE handle;
Py_BEGIN_ALLOW_THREADS
handle = CreateFileMappingW(file_handle, security_attributes,
protect, max_size_high, max_size_low,
name);
Py_END_ALLOW_THREADS
if (handle == NULL) {
PyErr_SetFromWindowsErrWithUnicodeFilename(0, name);
handle = INVALID_HANDLE_VALUE;
}
return handle;
}
/*[clinic input]
_winapi.CreateJunction
......@@ -1295,6 +1340,64 @@ _winapi_GetVersion_impl(PyObject *module)
#pragma warning(pop)
/*[clinic input]
_winapi.MapViewOfFile -> LPVOID
file_map: HANDLE
desired_access: DWORD
file_offset_high: DWORD
file_offset_low: DWORD
number_bytes: size_t
/
[clinic start generated code]*/
static LPVOID
_winapi_MapViewOfFile_impl(PyObject *module, HANDLE file_map,
DWORD desired_access, DWORD file_offset_high,
DWORD file_offset_low, size_t number_bytes)
/*[clinic end generated code: output=f23b1ee4823663e3 input=177471073be1a103]*/
{
LPVOID address;
Py_BEGIN_ALLOW_THREADS
address = MapViewOfFile(file_map, desired_access, file_offset_high,
file_offset_low, number_bytes);
Py_END_ALLOW_THREADS
if (address == NULL)
PyErr_SetFromWindowsErr(0);
return address;
}
/*[clinic input]
_winapi.OpenFileMapping -> HANDLE
desired_access: DWORD
inherit_handle: BOOL
name: LPCWSTR
/
[clinic start generated code]*/
static HANDLE
_winapi_OpenFileMapping_impl(PyObject *module, DWORD desired_access,
BOOL inherit_handle, LPCWSTR name)
/*[clinic end generated code: output=08cc44def1cb11f1 input=131f2a405359de7f]*/
{
HANDLE handle;
Py_BEGIN_ALLOW_THREADS
handle = OpenFileMappingW(desired_access, inherit_handle, name);
Py_END_ALLOW_THREADS
if (handle == NULL) {
PyErr_SetFromWindowsErrWithUnicodeFilename(0, name);
handle = INVALID_HANDLE_VALUE;
}
return handle;
}
/*[clinic input]
_winapi.OpenProcess -> HANDLE
......@@ -1490,6 +1593,32 @@ _winapi_TerminateProcess_impl(PyObject *module, HANDLE handle,
Py_RETURN_NONE;
}
/*[clinic input]
_winapi.VirtualQuerySize -> size_t
address: LPCVOID
/
[clinic start generated code]*/
static size_t
_winapi_VirtualQuerySize_impl(PyObject *module, LPCVOID address)
/*[clinic end generated code: output=40c8e0ff5ec964df input=6b784a69755d0bb6]*/
{
SIZE_T size_of_buf;
MEMORY_BASIC_INFORMATION mem_basic_info;
SIZE_T region_size;
Py_BEGIN_ALLOW_THREADS
size_of_buf = VirtualQuery(address, &mem_basic_info, sizeof(mem_basic_info));
Py_END_ALLOW_THREADS
if (size_of_buf == 0)
PyErr_SetFromWindowsErr(0);
region_size = mem_basic_info.RegionSize;
return region_size;
}
/*[clinic input]
_winapi.WaitNamedPipe
......@@ -1719,6 +1848,7 @@ static PyMethodDef winapi_functions[] = {
_WINAPI_CLOSEHANDLE_METHODDEF
_WINAPI_CONNECTNAMEDPIPE_METHODDEF
_WINAPI_CREATEFILE_METHODDEF
_WINAPI_CREATEFILEMAPPING_METHODDEF
_WINAPI_CREATENAMEDPIPE_METHODDEF
_WINAPI_CREATEPIPE_METHODDEF
_WINAPI_CREATEPROCESS_METHODDEF
......@@ -1731,11 +1861,14 @@ static PyMethodDef winapi_functions[] = {
_WINAPI_GETMODULEFILENAME_METHODDEF
_WINAPI_GETSTDHANDLE_METHODDEF
_WINAPI_GETVERSION_METHODDEF
_WINAPI_MAPVIEWOFFILE_METHODDEF
_WINAPI_OPENFILEMAPPING_METHODDEF
_WINAPI_OPENPROCESS_METHODDEF
_WINAPI_PEEKNAMEDPIPE_METHODDEF
_WINAPI_READFILE_METHODDEF
_WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF
_WINAPI_TERMINATEPROCESS_METHODDEF
_WINAPI_VIRTUALQUERYSIZE_METHODDEF
_WINAPI_WAITNAMEDPIPE_METHODDEF
_WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF
_WINAPI_WAITFORSINGLEOBJECT_METHODDEF
......@@ -1799,11 +1932,34 @@ PyInit__winapi(void)
WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED);
WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_READ);
WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_WRITE);
WINAPI_CONSTANT(F_DWORD, FILE_MAP_ALL_ACCESS);
WINAPI_CONSTANT(F_DWORD, FILE_MAP_COPY);
WINAPI_CONSTANT(F_DWORD, FILE_MAP_EXECUTE);
WINAPI_CONSTANT(F_DWORD, FILE_MAP_READ);
WINAPI_CONSTANT(F_DWORD, FILE_MAP_WRITE);
WINAPI_CONSTANT(F_DWORD, GENERIC_READ);
WINAPI_CONSTANT(F_DWORD, GENERIC_WRITE);
WINAPI_CONSTANT(F_DWORD, INFINITE);
WINAPI_CONSTANT(F_HANDLE, INVALID_HANDLE_VALUE);
WINAPI_CONSTANT(F_DWORD, MEM_COMMIT);
WINAPI_CONSTANT(F_DWORD, MEM_FREE);
WINAPI_CONSTANT(F_DWORD, MEM_IMAGE);
WINAPI_CONSTANT(F_DWORD, MEM_MAPPED);
WINAPI_CONSTANT(F_DWORD, MEM_PRIVATE);
WINAPI_CONSTANT(F_DWORD, MEM_RESERVE);
WINAPI_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER);
WINAPI_CONSTANT(F_DWORD, OPEN_EXISTING);
WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE);
WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_READ);
WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_READWRITE);
WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_WRITECOPY);
WINAPI_CONSTANT(F_DWORD, PAGE_GUARD);
WINAPI_CONSTANT(F_DWORD, PAGE_NOACCESS);
WINAPI_CONSTANT(F_DWORD, PAGE_NOCACHE);
WINAPI_CONSTANT(F_DWORD, PAGE_READONLY);
WINAPI_CONSTANT(F_DWORD, PAGE_READWRITE);
WINAPI_CONSTANT(F_DWORD, PAGE_WRITECOMBINE);
WINAPI_CONSTANT(F_DWORD, PAGE_WRITECOPY);
WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX);
WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND);
WINAPI_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE);
......@@ -1812,6 +1968,12 @@ PyInit__winapi(void)
WINAPI_CONSTANT(F_DWORD, PIPE_WAIT);
WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS);
WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE);
WINAPI_CONSTANT(F_DWORD, SEC_COMMIT);
WINAPI_CONSTANT(F_DWORD, SEC_IMAGE);
WINAPI_CONSTANT(F_DWORD, SEC_LARGE_PAGES);
WINAPI_CONSTANT(F_DWORD, SEC_NOCACHE);
WINAPI_CONSTANT(F_DWORD, SEC_RESERVE);
WINAPI_CONSTANT(F_DWORD, SEC_WRITECOMBINE);
WINAPI_CONSTANT(F_DWORD, STARTF_USESHOWWINDOW);
WINAPI_CONSTANT(F_DWORD, STARTF_USESTDHANDLES);
WINAPI_CONSTANT(F_DWORD, STD_INPUT_HANDLE);
......
......@@ -168,6 +168,50 @@ exit:
return return_value;
}
PyDoc_STRVAR(_winapi_CreateFileMapping__doc__,
"CreateFileMapping($module, file_handle, security_attributes, protect,\n"
" max_size_high, max_size_low, name, /)\n"
"--\n"
"\n");
#define _WINAPI_CREATEFILEMAPPING_METHODDEF \
{"CreateFileMapping", (PyCFunction)(void(*)(void))_winapi_CreateFileMapping, METH_FASTCALL, _winapi_CreateFileMapping__doc__},
static HANDLE
_winapi_CreateFileMapping_impl(PyObject *module, HANDLE file_handle,
LPSECURITY_ATTRIBUTES security_attributes,
DWORD protect, DWORD max_size_high,
DWORD max_size_low, LPCWSTR name);
static PyObject *
_winapi_CreateFileMapping(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
HANDLE file_handle;
LPSECURITY_ATTRIBUTES security_attributes;
DWORD protect;
DWORD max_size_high;
DWORD max_size_low;
LPCWSTR name;
HANDLE _return_value;
if (!_PyArg_ParseStack(args, nargs, "" F_HANDLE "" F_POINTER "kkku:CreateFileMapping",
&file_handle, &security_attributes, &protect, &max_size_high, &max_size_low, &name)) {
goto exit;
}
_return_value = _winapi_CreateFileMapping_impl(module, file_handle, security_attributes, protect, max_size_high, max_size_low, name);
if ((_return_value == INVALID_HANDLE_VALUE) && PyErr_Occurred()) {
goto exit;
}
if (_return_value == NULL) {
Py_RETURN_NONE;
}
return_value = HANDLE_TO_PYNUM(_return_value);
exit:
return return_value;
}
PyDoc_STRVAR(_winapi_CreateJunction__doc__,
"CreateJunction($module, src_path, dst_path, /)\n"
"--\n"
......@@ -602,6 +646,83 @@ exit:
return return_value;
}
PyDoc_STRVAR(_winapi_MapViewOfFile__doc__,
"MapViewOfFile($module, file_map, desired_access, file_offset_high,\n"
" file_offset_low, number_bytes, /)\n"
"--\n"
"\n");
#define _WINAPI_MAPVIEWOFFILE_METHODDEF \
{"MapViewOfFile", (PyCFunction)(void(*)(void))_winapi_MapViewOfFile, METH_FASTCALL, _winapi_MapViewOfFile__doc__},
static LPVOID
_winapi_MapViewOfFile_impl(PyObject *module, HANDLE file_map,
DWORD desired_access, DWORD file_offset_high,
DWORD file_offset_low, size_t number_bytes);
static PyObject *
_winapi_MapViewOfFile(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
HANDLE file_map;
DWORD desired_access;
DWORD file_offset_high;
DWORD file_offset_low;
size_t number_bytes;
LPVOID _return_value;
if (!_PyArg_ParseStack(args, nargs, "" F_HANDLE "kkkO&:MapViewOfFile",
&file_map, &desired_access, &file_offset_high, &file_offset_low, _PyLong_Size_t_Converter, &number_bytes)) {
goto exit;
}
_return_value = _winapi_MapViewOfFile_impl(module, file_map, desired_access, file_offset_high, file_offset_low, number_bytes);
if ((_return_value == NULL) && PyErr_Occurred()) {
goto exit;
}
return_value = HANDLE_TO_PYNUM(_return_value);
exit:
return return_value;
}
PyDoc_STRVAR(_winapi_OpenFileMapping__doc__,
"OpenFileMapping($module, desired_access, inherit_handle, name, /)\n"
"--\n"
"\n");
#define _WINAPI_OPENFILEMAPPING_METHODDEF \
{"OpenFileMapping", (PyCFunction)(void(*)(void))_winapi_OpenFileMapping, METH_FASTCALL, _winapi_OpenFileMapping__doc__},
static HANDLE
_winapi_OpenFileMapping_impl(PyObject *module, DWORD desired_access,
BOOL inherit_handle, LPCWSTR name);
static PyObject *
_winapi_OpenFileMapping(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
DWORD desired_access;
BOOL inherit_handle;
LPCWSTR name;
HANDLE _return_value;
if (!_PyArg_ParseStack(args, nargs, "kiu:OpenFileMapping",
&desired_access, &inherit_handle, &name)) {
goto exit;
}
_return_value = _winapi_OpenFileMapping_impl(module, desired_access, inherit_handle, name);
if ((_return_value == INVALID_HANDLE_VALUE) && PyErr_Occurred()) {
goto exit;
}
if (_return_value == NULL) {
Py_RETURN_NONE;
}
return_value = HANDLE_TO_PYNUM(_return_value);
exit:
return return_value;
}
PyDoc_STRVAR(_winapi_OpenProcess__doc__,
"OpenProcess($module, desired_access, inherit_handle, process_id, /)\n"
"--\n"
......@@ -764,6 +885,37 @@ exit:
return return_value;
}
PyDoc_STRVAR(_winapi_VirtualQuerySize__doc__,
"VirtualQuerySize($module, address, /)\n"
"--\n"
"\n");
#define _WINAPI_VIRTUALQUERYSIZE_METHODDEF \
{"VirtualQuerySize", (PyCFunction)_winapi_VirtualQuerySize, METH_O, _winapi_VirtualQuerySize__doc__},
static size_t
_winapi_VirtualQuerySize_impl(PyObject *module, LPCVOID address);
static PyObject *
_winapi_VirtualQuerySize(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
LPCVOID address;
size_t _return_value;
if (!PyArg_Parse(arg, "" F_POINTER ":VirtualQuerySize", &address)) {
goto exit;
}
_return_value = _winapi_VirtualQuerySize_impl(module, address);
if ((_return_value == (size_t)-1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyLong_FromSize_t(_return_value);
exit:
return return_value;
}
PyDoc_STRVAR(_winapi_WaitNamedPipe__doc__,
"WaitNamedPipe($module, name, timeout, /)\n"
"--\n"
......@@ -945,4 +1097,4 @@ _winapi_GetFileType(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
exit:
return return_value;
}
/*[clinic end generated code: output=5063c84b2d125488 input=a9049054013a1b77]*/
/*[clinic end generated code: output=f3897898ea1da99d input=a9049054013a1b77]*/
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment