[Python-checkins] bpo-47003: Cleanup _overlapped module (GH-31848)

asvetlov webhook-mailer at python.org
Sun Mar 13 17:29:06 EDT 2022


https://github.com/python/cpython/commit/690490e4de9f2baf07171b3d63fc440239928fb4
commit: 690490e4de9f2baf07171b3d63fc440239928fb4
branch: main
author: Andrew Svetlov <andrew.svetlov at gmail.com>
committer: asvetlov <andrew.svetlov at gmail.com>
date: 2022-03-13T23:28:45+02:00
summary:

bpo-47003: Cleanup _overlapped module (GH-31848)

files:
M Modules/clinic/overlapped.c.h
M Modules/overlapped.c

diff --git a/Modules/clinic/overlapped.c.h b/Modules/clinic/overlapped.c.h
index 16d6013ef2f2e..7e81fc8f97104 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 ab9a2f0ce26f6..74fba8346c2e1 100644
--- a/Modules/overlapped.c
+++ b/Modules/overlapped.c
@@ -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
  */
@@ -150,7 +157,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,    \
@@ -164,10 +170,19 @@ initialize_function_pointers(void)
     GUID GuidConnectEx = WSAID_CONNECTEX;
     GUID GuidDisconnectEx = WSAID_DISCONNECTEX;
     GUID GuidTransmitFile = WSAID_TRANSMITFILE;
-    HINSTANCE hKernel32;
     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 +200,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 +605,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;
@@ -678,6 +687,9 @@ 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:
@@ -704,10 +716,10 @@ Overlapped_dealloc(OverlappedObject *self)
     if (!HasOverlappedIoCompleted(&self->overlapped) &&
         self->type != TYPE_NOT_STARTED)
     {
-        if (Py_CancelIoEx && Py_CancelIoEx(self->handle, &self->overlapped))
+        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
@@ -820,10 +832,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 +1043,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 +1051,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
+    steal_buffer(&self->user_buffer, bufobj);
 
     self->type = TYPE_READINTO;
     self->handle = handle;
@@ -1142,7 +1148,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 +1157,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
+    steal_buffer(&self->user_buffer, bufobj);
 
     self->type = TYPE_READINTO;
     self->handle = handle;
@@ -1182,7 +1185,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 +1193,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 +1205,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
+    steal_buffer(&self->user_buffer, bufobj);
 
     self->type = TYPE_WRITE;
     self->handle = handle;
@@ -1237,7 +1237,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 +1246,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 +1259,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
+    steal_buffer(&self->user_buffer, bufobj);
 
     self->type = TYPE_WRITE;
     self->handle = handle;
@@ -1668,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;
     }
@@ -1728,7 +1725,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 +1735,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 +1759,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
+    steal_buffer(&self->user_buffer, bufobj);
 
     self->type = TYPE_WRITE_TO;
     self->handle = handle;
@@ -1912,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);
 



More information about the Python-checkins mailing list