From 8f635f442d8f3ba35bbc6fed937b8ee394058662 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sun, 13 Mar 2022 19:13:24 +0200 Subject: [PATCH 1/5] Cleanup _overlapped module --- Modules/clinic/overlapped.c.h | 67 +++++++++++++++++-------- Modules/overlapped.c | 92 +++++++++++++++-------------------- 2 files changed, 84 insertions(+), 75 deletions(-) diff --git a/Modules/clinic/overlapped.c.h b/Modules/clinic/overlapped.c.h index 16d6013ef2f2e5..7e81fc8f97104f 100644 --- a/Modules/clinic/overlapped.c.h +++ b/Modules/clinic/overlapped.c.h @@ -466,22 +466,27 @@ PyDoc_STRVAR(_overlapped_Overlapped_ReadFileInto__doc__, static PyObject * _overlapped_Overlapped_ReadFileInto_impl(OverlappedObject *self, - HANDLE handle, PyObject *bufobj); + HANDLE handle, Py_buffer *bufobj); static PyObject * _overlapped_Overlapped_ReadFileInto(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HANDLE handle; - PyObject *bufobj; + Py_buffer bufobj = {NULL, NULL}; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"O:ReadFileInto", + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"y*:ReadFileInto", &handle, &bufobj)) { goto exit; } - return_value = _overlapped_Overlapped_ReadFileInto_impl(self, handle, bufobj); + return_value = _overlapped_Overlapped_ReadFileInto_impl(self, handle, &bufobj); exit: + /* Cleanup for bufobj */ + if (bufobj.obj) { + PyBuffer_Release(&bufobj); + } + return return_value; } @@ -527,7 +532,7 @@ PyDoc_STRVAR(_overlapped_Overlapped_WSARecvInto__doc__, static PyObject * _overlapped_Overlapped_WSARecvInto_impl(OverlappedObject *self, - HANDLE handle, PyObject *bufobj, + HANDLE handle, Py_buffer *bufobj, DWORD flags); static PyObject * @@ -535,16 +540,21 @@ _overlapped_Overlapped_WSARecvInto(OverlappedObject *self, PyObject *const *args { PyObject *return_value = NULL; HANDLE handle; - PyObject *bufobj; + Py_buffer bufobj = {NULL, NULL}; DWORD flags; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"Ok:WSARecvInto", + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"y*k:WSARecvInto", &handle, &bufobj, &flags)) { goto exit; } - return_value = _overlapped_Overlapped_WSARecvInto_impl(self, handle, bufobj, flags); + return_value = _overlapped_Overlapped_WSARecvInto_impl(self, handle, &bufobj, flags); exit: + /* Cleanup for bufobj */ + if (bufobj.obj) { + PyBuffer_Release(&bufobj); + } + return return_value; } @@ -559,22 +569,27 @@ PyDoc_STRVAR(_overlapped_Overlapped_WriteFile__doc__, static PyObject * _overlapped_Overlapped_WriteFile_impl(OverlappedObject *self, HANDLE handle, - PyObject *bufobj); + Py_buffer *bufobj); static PyObject * _overlapped_Overlapped_WriteFile(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HANDLE handle; - PyObject *bufobj; + Py_buffer bufobj = {NULL, NULL}; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"O:WriteFile", + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"y*:WriteFile", &handle, &bufobj)) { goto exit; } - return_value = _overlapped_Overlapped_WriteFile_impl(self, handle, bufobj); + return_value = _overlapped_Overlapped_WriteFile_impl(self, handle, &bufobj); exit: + /* Cleanup for bufobj */ + if (bufobj.obj) { + PyBuffer_Release(&bufobj); + } + return return_value; } @@ -589,23 +604,28 @@ PyDoc_STRVAR(_overlapped_Overlapped_WSASend__doc__, static PyObject * _overlapped_Overlapped_WSASend_impl(OverlappedObject *self, HANDLE handle, - PyObject *bufobj, DWORD flags); + Py_buffer *bufobj, DWORD flags); static PyObject * _overlapped_Overlapped_WSASend(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; HANDLE handle; - PyObject *bufobj; + Py_buffer bufobj = {NULL, NULL}; DWORD flags; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"Ok:WSASend", + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"y*k:WSASend", &handle, &bufobj, &flags)) { goto exit; } - return_value = _overlapped_Overlapped_WSASend_impl(self, handle, bufobj, flags); + return_value = _overlapped_Overlapped_WSASend_impl(self, handle, &bufobj, flags); exit: + /* Cleanup for bufobj */ + if (bufobj.obj) { + PyBuffer_Release(&bufobj); + } + return return_value; } @@ -852,7 +872,7 @@ PyDoc_STRVAR(_overlapped_Overlapped_WSASendTo__doc__, static PyObject * _overlapped_Overlapped_WSASendTo_impl(OverlappedObject *self, HANDLE handle, - PyObject *bufobj, DWORD flags, + Py_buffer *bufobj, DWORD flags, PyObject *AddressObj); static PyObject * @@ -860,17 +880,22 @@ _overlapped_Overlapped_WSASendTo(OverlappedObject *self, PyObject *const *args, { PyObject *return_value = NULL; HANDLE handle; - PyObject *bufobj; + Py_buffer bufobj = {NULL, NULL}; DWORD flags; PyObject *AddressObj; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"OkO:WSASendTo", + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"y*kO:WSASendTo", &handle, &bufobj, &flags, &AddressObj)) { goto exit; } - return_value = _overlapped_Overlapped_WSASendTo_impl(self, handle, bufobj, flags, AddressObj); + return_value = _overlapped_Overlapped_WSASendTo_impl(self, handle, &bufobj, flags, AddressObj); exit: + /* Cleanup for bufobj */ + if (bufobj.obj) { + PyBuffer_Release(&bufobj); + } + return return_value; } @@ -943,4 +968,4 @@ _overlapped_Overlapped_WSARecvFromInto(OverlappedObject *self, PyObject *const * return return_value; } -/*[clinic end generated code: output=5c9b17890ef29d52 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d19a061ea7398d23 input=a9049054013a1b77]*/ diff --git a/Modules/overlapped.c b/Modules/overlapped.c index ab9a2f0ce26f62..e6e991dd6df1d6 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -150,7 +150,6 @@ static LPFN_ACCEPTEX Py_AcceptEx = NULL; static LPFN_CONNECTEX Py_ConnectEx = NULL; static LPFN_DISCONNECTEX Py_DisconnectEx = NULL; static LPFN_TRANSMITFILE Py_TransmitFile = NULL; -static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED) = NULL; #define GET_WSA_POINTER(s, x) \ (SOCKET_ERROR != WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, \ @@ -168,6 +167,16 @@ initialize_function_pointers(void) SOCKET s; DWORD dwBytes; + if (Py_AcceptEx != NULL && + Py_ConnectEx != NULL && + Py_DisconnectEx != NULL && + Py_TransmitFile != NULL) + { + // All function pointers are initialized already + // by previous module import + return 0; + } + s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == INVALID_SOCKET) { SetFromWindowsErr(WSAGetLastError()); @@ -185,12 +194,6 @@ initialize_function_pointers(void) } closesocket(s); - - /* On WinXP we will have Py_CancelIoEx == NULL */ - Py_BEGIN_ALLOW_THREADS - hKernel32 = GetModuleHandle("KERNEL32"); - *(FARPROC *)&Py_CancelIoEx = GetProcAddress(hKernel32, "CancelIoEx"); - Py_END_ALLOW_THREADS return 0; } @@ -596,7 +599,7 @@ _overlapped_FormatMessage_impl(PyObject *module, DWORD code) * Mark operation as completed - used when reading produces ERROR_BROKEN_PIPE */ -static void +static inline void mark_as_completed(OVERLAPPED *ov) { ov->Internal = 0; @@ -704,7 +707,7 @@ Overlapped_dealloc(OverlappedObject *self) if (!HasOverlappedIoCompleted(&self->overlapped) && self->type != TYPE_NOT_STARTED) { - if (Py_CancelIoEx && Py_CancelIoEx(self->handle, &self->overlapped)) + if (CancelIoEx(self->handle, &self->overlapped)) wait = TRUE; Py_BEGIN_ALLOW_THREADS @@ -820,10 +823,7 @@ _overlapped_Overlapped_cancel_impl(OverlappedObject *self) if (!HasOverlappedIoCompleted(&self->overlapped)) { Py_BEGIN_ALLOW_THREADS - if (Py_CancelIoEx) - ret = Py_CancelIoEx(self->handle, &self->overlapped); - else - ret = CancelIo(self->handle); + ret = CancelIoEx(self->handle, &self->overlapped); Py_END_ALLOW_THREADS } @@ -1034,7 +1034,7 @@ _overlapped_Overlapped_ReadFile_impl(OverlappedObject *self, HANDLE handle, _overlapped.Overlapped.ReadFileInto handle: HANDLE - buf as bufobj: object + buf as bufobj: Py_buffer / Start overlapped receive. @@ -1042,24 +1042,21 @@ Start overlapped receive. static PyObject * _overlapped_Overlapped_ReadFileInto_impl(OverlappedObject *self, - HANDLE handle, PyObject *bufobj) -/*[clinic end generated code: output=1e9e712e742e5b2a input=16f6cc268d1d0387]*/ + HANDLE handle, Py_buffer *bufobj) +/*[clinic end generated code: output=8754744506023071 input=4f037ba09939e32d]*/ { if (self->type != TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation already attempted"); return NULL; } - if (!PyArg_Parse(bufobj, "y*", &self->user_buffer)) - return NULL; - #if SIZEOF_SIZE_T > SIZEOF_LONG - if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) { - PyBuffer_Release(&self->user_buffer); + if (bufobj->len > (Py_ssize_t)ULONG_MAX) { PyErr_SetString(PyExc_ValueError, "buffer too large"); return NULL; } #endif + self->user_buffer = bufobj; self->type = TYPE_READINTO; self->handle = handle; @@ -1142,7 +1139,7 @@ _overlapped_Overlapped_WSARecv_impl(OverlappedObject *self, HANDLE handle, _overlapped.Overlapped.WSARecvInto handle: HANDLE - buf as bufobj: object + buf as bufobj: Py_buffer flags: DWORD / @@ -1151,25 +1148,22 @@ Start overlapped receive. static PyObject * _overlapped_Overlapped_WSARecvInto_impl(OverlappedObject *self, - HANDLE handle, PyObject *bufobj, + HANDLE handle, Py_buffer *bufobj, DWORD flags) -/*[clinic end generated code: output=9a438abc436fe87c input=4f87c38fc381d525]*/ +/*[clinic end generated code: output=59ae7688786cf86b input=73e7fa00db633edd]*/ { if (self->type != TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation already attempted"); return NULL; } - if (!PyArg_Parse(bufobj, "y*", &self->user_buffer)) - return NULL; - #if SIZEOF_SIZE_T > SIZEOF_LONG - if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) { - PyBuffer_Release(&self->user_buffer); + if (bufobj->len > (Py_ssize_t)ULONG_MAX) { PyErr_SetString(PyExc_ValueError, "buffer too large"); return NULL; } #endif + self->user_buffer = bufobj; self->type = TYPE_READINTO; self->handle = handle; @@ -1182,7 +1176,7 @@ _overlapped_Overlapped_WSARecvInto_impl(OverlappedObject *self, _overlapped.Overlapped.WriteFile handle: HANDLE - buf as bufobj: object + buf as bufobj: Py_buffer / Start overlapped write. @@ -1190,8 +1184,8 @@ Start overlapped write. static PyObject * _overlapped_Overlapped_WriteFile_impl(OverlappedObject *self, HANDLE handle, - PyObject *bufobj) -/*[clinic end generated code: output=c376230b6120d877 input=b8d9a7608d8a1e72]*/ + Py_buffer *bufobj) +/*[clinic end generated code: output=fa5d5880a1bf04b1 input=ac54424c362abfc1]*/ { DWORD written; BOOL ret; @@ -1202,16 +1196,13 @@ _overlapped_Overlapped_WriteFile_impl(OverlappedObject *self, HANDLE handle, return NULL; } - if (!PyArg_Parse(bufobj, "y*", &self->user_buffer)) - return NULL; - #if SIZEOF_SIZE_T > SIZEOF_LONG - if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) { - PyBuffer_Release(&self->user_buffer); + if (bufobj->len > (Py_ssize_t)ULONG_MAX) { PyErr_SetString(PyExc_ValueError, "buffer too large"); return NULL; } #endif + self->user_buffer = bufobj; self->type = TYPE_WRITE; self->handle = handle; @@ -1237,7 +1228,7 @@ _overlapped_Overlapped_WriteFile_impl(OverlappedObject *self, HANDLE handle, _overlapped.Overlapped.WSASend handle: HANDLE - buf as bufobj: object + buf as bufobj: Py_buffer flags: DWORD / @@ -1246,8 +1237,8 @@ Start overlapped send. static PyObject * _overlapped_Overlapped_WSASend_impl(OverlappedObject *self, HANDLE handle, - PyObject *bufobj, DWORD flags) -/*[clinic end generated code: output=316031c7467040cc input=932e7cba6d18f708]*/ + Py_buffer *bufobj, DWORD flags) +/*[clinic end generated code: output=3baaa6e1f7fe229e input=c4167420ba2f93d8]*/ { DWORD written; WSABUF wsabuf; @@ -1259,16 +1250,13 @@ _overlapped_Overlapped_WSASend_impl(OverlappedObject *self, HANDLE handle, return NULL; } - if (!PyArg_Parse(bufobj, "y*", &self->user_buffer)) - return NULL; - #if SIZEOF_SIZE_T > SIZEOF_LONG - if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) { - PyBuffer_Release(&self->user_buffer); + if (bufobj->len > (Py_ssize_t)ULONG_MAX) { PyErr_SetString(PyExc_ValueError, "buffer too large"); return NULL; } #endif + self->user_buffer = bufobj; self->type = TYPE_WRITE; self->handle = handle; @@ -1728,7 +1716,7 @@ _overlapped_WSAConnect_impl(PyObject *module, HANDLE ConnectSocket, _overlapped.Overlapped.WSASendTo handle: HANDLE - buf as bufobj: object + buf as bufobj: Py_buffer flags: DWORD address_as_bytes as AddressObj: object / @@ -1738,9 +1726,9 @@ Start overlapped sendto over a connectionless (UDP) socket. static PyObject * _overlapped_Overlapped_WSASendTo_impl(OverlappedObject *self, HANDLE handle, - PyObject *bufobj, DWORD flags, + Py_buffer *bufobj, DWORD flags, PyObject *AddressObj) -/*[clinic end generated code: output=fe0ff55eb60d65e1 input=f709e6ecebd9bc18]*/ +/*[clinic end generated code: output=3cdedc4cfaeb70cd input=b7c1749a62e2e374]*/ { char AddressBuf[sizeof(struct sockaddr_in6)]; SOCKADDR *Address = (SOCKADDR*)AddressBuf; @@ -1762,17 +1750,13 @@ _overlapped_Overlapped_WSASendTo_impl(OverlappedObject *self, HANDLE handle, return NULL; } - if (!PyArg_Parse(bufobj, "y*", &self->user_buffer)) { - return NULL; - } - #if SIZEOF_SIZE_T > SIZEOF_LONG - if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) { - PyBuffer_Release(&self->user_buffer); + if (bufobj->len > (Py_ssize_t)ULONG_MAX) { PyErr_SetString(PyExc_ValueError, "buffer too large"); return NULL; } #endif + self->user_buffer = bufobj; self->type = TYPE_WRITE_TO; self->handle = handle; From 2243f0b4cf5a76a6cd48ac4b5ba6bf8d6ea14be3 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sun, 13 Mar 2022 19:16:48 +0200 Subject: [PATCH 2/5] Run CancelIOEx with GIL released --- Modules/overlapped.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/overlapped.c b/Modules/overlapped.c index e6e991dd6df1d6..e36865303b0cf2 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -707,10 +707,10 @@ Overlapped_dealloc(OverlappedObject *self) if (!HasOverlappedIoCompleted(&self->overlapped) && self->type != TYPE_NOT_STARTED) { + Py_BEGIN_ALLOW_THREADS if (CancelIoEx(self->handle, &self->overlapped)) wait = TRUE; - Py_BEGIN_ALLOW_THREADS ret = GetOverlappedResult(self->handle, &self->overlapped, &bytes, wait); Py_END_ALLOW_THREADS From 357df44fcef6df98497eb7178183e01775eb3209 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sun, 13 Mar 2022 19:30:11 +0200 Subject: [PATCH 3/5] Fix compiler errors --- Modules/overlapped.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/Modules/overlapped.c b/Modules/overlapped.c index e36865303b0cf2..cdf52ecc6f3beb 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -79,7 +79,7 @@ typedef struct { /* Buffer allocated by us: TYPE_READ and TYPE_ACCEPT */ PyObject *allocated_buffer; /* Buffer passed by the user: TYPE_WRITE, TYPE_WRITE_TO, and TYPE_READINTO */ - Py_buffer user_buffer; + Py_buffer *user_buffer; /* Data used for reading from a connectionless socket: TYPE_READ_FROM */ @@ -163,7 +163,6 @@ initialize_function_pointers(void) GUID GuidConnectEx = WSAID_CONNECTEX; GUID GuidDisconnectEx = WSAID_DISCONNECTEX; GUID GuidTransmitFile = WSAID_TRANSMITFILE; - HINSTANCE hKernel32; SOCKET s; DWORD dwBytes; @@ -645,7 +644,7 @@ _overlapped_Overlapped_impl(PyTypeObject *type, HANDLE event) self->type = TYPE_NONE; self->allocated_buffer = NULL; memset(&self->overlapped, 0, sizeof(OVERLAPPED)); - memset(&self->user_buffer, 0, sizeof(Py_buffer)); + memset(self->user_buffer, 0, sizeof(Py_buffer)); if (event) self->overlapped.hEvent = event; return (PyObject *)self; @@ -686,8 +685,8 @@ Overlapped_clear(OverlappedObject *self) case TYPE_WRITE: case TYPE_WRITE_TO: case TYPE_READINTO: { - if (self->user_buffer.obj) { - PyBuffer_Release(&self->user_buffer); + if (self->user_buffer->obj) { + PyBuffer_Release(self->user_buffer); } break; } @@ -1061,8 +1060,8 @@ _overlapped_Overlapped_ReadFileInto_impl(OverlappedObject *self, self->type = TYPE_READINTO; self->handle = handle; - return do_ReadFile(self, handle, self->user_buffer.buf, - (DWORD)self->user_buffer.len); + return do_ReadFile(self, handle, self->user_buffer->buf, + (DWORD)self->user_buffer->len); } static PyObject * @@ -1168,8 +1167,8 @@ _overlapped_Overlapped_WSARecvInto_impl(OverlappedObject *self, self->type = TYPE_READINTO; self->handle = handle; - return do_WSARecv(self, handle, self->user_buffer.buf, - (DWORD)self->user_buffer.len, flags); + return do_WSARecv(self, handle, self->user_buffer->buf, + (DWORD)self->user_buffer->len, flags); } /*[clinic input] @@ -1208,8 +1207,8 @@ _overlapped_Overlapped_WriteFile_impl(OverlappedObject *self, HANDLE handle, self->handle = handle; Py_BEGIN_ALLOW_THREADS - ret = WriteFile(handle, self->user_buffer.buf, - (DWORD)self->user_buffer.len, + ret = WriteFile(handle, self->user_buffer->buf, + (DWORD)self->user_buffer->len, &written, &self->overlapped); Py_END_ALLOW_THREADS @@ -1260,8 +1259,8 @@ _overlapped_Overlapped_WSASend_impl(OverlappedObject *self, HANDLE handle, self->type = TYPE_WRITE; self->handle = handle; - wsabuf.len = (DWORD)self->user_buffer.len; - wsabuf.buf = self->user_buffer.buf; + wsabuf.len = (DWORD)self->user_buffer->len; + wsabuf.buf = self->user_buffer->buf; Py_BEGIN_ALLOW_THREADS ret = WSASend((SOCKET)handle, &wsabuf, 1, &written, flags, @@ -1646,8 +1645,8 @@ Overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg) case TYPE_WRITE: case TYPE_WRITE_TO: case TYPE_READINTO: - if (self->user_buffer.obj) { - Py_VISIT(&self->user_buffer.obj); + if (self->user_buffer->obj) { + Py_VISIT(&self->user_buffer->obj); } break; case TYPE_READ_FROM: @@ -1760,8 +1759,8 @@ _overlapped_Overlapped_WSASendTo_impl(OverlappedObject *self, HANDLE handle, self->type = TYPE_WRITE_TO; self->handle = handle; - wsabuf.len = (DWORD)self->user_buffer.len; - wsabuf.buf = self->user_buffer.buf; + wsabuf.len = (DWORD)self->user_buffer->len; + wsabuf.buf = self->user_buffer->buf; Py_BEGIN_ALLOW_THREADS ret = WSASendTo((SOCKET)handle, &wsabuf, 1, &written, flags, From 720fd84e2151abff16d3cb8595e758950346b3f5 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sun, 13 Mar 2022 20:21:17 +0200 Subject: [PATCH 4/5] Fix memory management --- Modules/overlapped.c | 60 ++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/Modules/overlapped.c b/Modules/overlapped.c index cdf52ecc6f3beb..a8747eb478469c 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -79,7 +79,7 @@ typedef struct { /* Buffer allocated by us: TYPE_READ and TYPE_ACCEPT */ PyObject *allocated_buffer; /* Buffer passed by the user: TYPE_WRITE, TYPE_WRITE_TO, and TYPE_READINTO */ - Py_buffer *user_buffer; + Py_buffer user_buffer; /* Data used for reading from a connectionless socket: TYPE_READ_FROM */ @@ -98,7 +98,7 @@ typedef struct { // A (number of bytes read, (host, port)) tuple PyObject* result; /* Buffer passed by the user */ - Py_buffer *user_buffer; + Py_buffer user_buffer; struct sockaddr_in6 address; int address_length; } read_from_into; @@ -118,6 +118,13 @@ overlapped_get_state(PyObject *module) } +static inline void +steal_buffer(Py_buffer * dst, Py_buffer * src) +{ + memcpy(dst, src, sizeof(Py_buffer)); + memset(src, 0, sizeof(Py_buffer)); +} + /* * Map Windows error codes to subclasses of OSError */ @@ -644,7 +651,7 @@ _overlapped_Overlapped_impl(PyTypeObject *type, HANDLE event) self->type = TYPE_NONE; self->allocated_buffer = NULL; memset(&self->overlapped, 0, sizeof(OVERLAPPED)); - memset(self->user_buffer, 0, sizeof(Py_buffer)); + memset(&self->user_buffer, 0, sizeof(Py_buffer)); if (event) self->overlapped.hEvent = event; return (PyObject *)self; @@ -680,13 +687,16 @@ Overlapped_clear(OverlappedObject *self) // We've received a message, free the result tuple. Py_CLEAR(self->read_from_into.result); } + if (self->read_from_into->user_buffer.obj) { + PyBuffer_Release(&self->read_from_into->user_buffer); + } break; } case TYPE_WRITE: case TYPE_WRITE_TO: case TYPE_READINTO: { - if (self->user_buffer->obj) { - PyBuffer_Release(self->user_buffer); + if (self->user_buffer.obj) { + PyBuffer_Release(&self->user_buffer); } break; } @@ -1055,13 +1065,13 @@ _overlapped_Overlapped_ReadFileInto_impl(OverlappedObject *self, return NULL; } #endif - self->user_buffer = bufobj; + steal_buffer(&self->user_buffer, bufobj); self->type = TYPE_READINTO; self->handle = handle; - return do_ReadFile(self, handle, self->user_buffer->buf, - (DWORD)self->user_buffer->len); + return do_ReadFile(self, handle, self->user_buffer.buf, + (DWORD)self->user_buffer.len); } static PyObject * @@ -1162,13 +1172,13 @@ _overlapped_Overlapped_WSARecvInto_impl(OverlappedObject *self, return NULL; } #endif - self->user_buffer = bufobj; + steal_buffer(&self->user_buffer, bufobj); self->type = TYPE_READINTO; self->handle = handle; - return do_WSARecv(self, handle, self->user_buffer->buf, - (DWORD)self->user_buffer->len, flags); + return do_WSARecv(self, handle, self->user_buffer.buf, + (DWORD)self->user_buffer.len, flags); } /*[clinic input] @@ -1201,14 +1211,14 @@ _overlapped_Overlapped_WriteFile_impl(OverlappedObject *self, HANDLE handle, return NULL; } #endif - self->user_buffer = bufobj; + steal_buffer(&self->user_buffer, bufobj); self->type = TYPE_WRITE; self->handle = handle; Py_BEGIN_ALLOW_THREADS - ret = WriteFile(handle, self->user_buffer->buf, - (DWORD)self->user_buffer->len, + ret = WriteFile(handle, self->user_buffer.buf, + (DWORD)self->user_buffer.len, &written, &self->overlapped); Py_END_ALLOW_THREADS @@ -1255,12 +1265,12 @@ _overlapped_Overlapped_WSASend_impl(OverlappedObject *self, HANDLE handle, return NULL; } #endif - self->user_buffer = bufobj; + steal_buffer(&self->user_buffer, bufobj); self->type = TYPE_WRITE; self->handle = handle; - wsabuf.len = (DWORD)self->user_buffer->len; - wsabuf.buf = self->user_buffer->buf; + wsabuf.len = (DWORD)self->user_buffer.len; + wsabuf.buf = self->user_buffer.buf; Py_BEGIN_ALLOW_THREADS ret = WSASend((SOCKET)handle, &wsabuf, 1, &written, flags, @@ -1645,8 +1655,8 @@ Overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg) case TYPE_WRITE: case TYPE_WRITE_TO: case TYPE_READINTO: - if (self->user_buffer->obj) { - Py_VISIT(&self->user_buffer->obj); + if (self->user_buffer.obj) { + Py_VISIT(&self->user_buffer.obj); } break; case TYPE_READ_FROM: @@ -1655,8 +1665,8 @@ Overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg) break; case TYPE_READ_FROM_INTO: Py_VISIT(self->read_from_into.result); - if (self->read_from_into.user_buffer->obj) { - Py_VISIT(&self->read_from_into.user_buffer->obj); + if (self->read_from_into.user_buffer.obj) { + Py_VISIT(&self->read_from_into.user_buffer.obj); } break; } @@ -1755,12 +1765,12 @@ _overlapped_Overlapped_WSASendTo_impl(OverlappedObject *self, HANDLE handle, return NULL; } #endif - self->user_buffer = bufobj; + steal_buffer(&self->user_buffer, bufobj); self->type = TYPE_WRITE_TO; self->handle = handle; - wsabuf.len = (DWORD)self->user_buffer->len; - wsabuf.buf = self->user_buffer->buf; + wsabuf.len = (DWORD)self->user_buffer.len; + wsabuf.buf = self->user_buffer.buf; Py_BEGIN_ALLOW_THREADS ret = WSASendTo((SOCKET)handle, &wsabuf, 1, &written, flags, @@ -1895,7 +1905,7 @@ _overlapped_Overlapped_WSARecvFromInto_impl(OverlappedObject *self, self->type = TYPE_READ_FROM_INTO; self->handle = handle; - self->read_from_into.user_buffer = bufobj; + steal_buffer(&self->read_from_into.user_buffer, bufobj); memset(&self->read_from_into.address, 0, sizeof(self->read_from_into.address)); self->read_from_into.address_length = sizeof(self->read_from_into.address); From 50b1380744dc8c45d5e0a707aff16d30b5b5c30b Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sun, 13 Mar 2022 20:28:56 +0200 Subject: [PATCH 5/5] Fix compile error --- Modules/overlapped.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/overlapped.c b/Modules/overlapped.c index a8747eb478469c..74fba8346c2e1c 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -687,8 +687,8 @@ Overlapped_clear(OverlappedObject *self) // We've received a message, free the result tuple. Py_CLEAR(self->read_from_into.result); } - if (self->read_from_into->user_buffer.obj) { - PyBuffer_Release(&self->read_from_into->user_buffer); + if (self->read_from_into.user_buffer.obj) { + PyBuffer_Release(&self->read_from_into.user_buffer); } break; }