From 3914dfe7d8e7a6525f4936650bafa73040a05ac3 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 10 Aug 2020 19:14:58 -0500 Subject: [PATCH 1/4] port overlapped to multi-phase --- Modules/overlapped.c | 171 +++++++++++++++++++++++++++---------------- 1 file changed, 106 insertions(+), 65 deletions(-) diff --git a/Modules/overlapped.c b/Modules/overlapped.c index 5e7a1bbba76787..a769da86dc624a 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -100,6 +100,19 @@ typedef struct { }; } OverlappedObject; +typedef struct { + PyTypeObject *overlapped_type; +} OverlappedState; + +static inline OverlappedState* +overlapped_get_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (OverlappedState *)state; +} + + /* * Map Windows error codes to subclasses of OSError */ @@ -706,8 +719,11 @@ Overlapped_dealloc(OverlappedObject *self) } Overlapped_clear(self); - PyObject_Del(self); SetLastError(olderr); + + PyTypeObject *tp = Py_TYPE(self); + PyObject_Del(self); + Py_DECREF(tp); } @@ -1846,45 +1862,22 @@ static PyGetSetDef Overlapped_getsets[] = { {NULL}, }; -PyTypeObject OverlappedType = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ "_overlapped.Overlapped", - /* tp_basicsize */ sizeof(OverlappedObject), - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor) Overlapped_dealloc, - /* tp_vectorcall_offset */ 0, - /* tp_getattr */ 0, - /* tp_setattr */ 0, - /* tp_as_async */ 0, - /* tp_repr */ 0, - /* tp_as_number */ 0, - /* tp_as_sequence */ 0, - /* tp_as_mapping */ 0, - /* tp_hash */ 0, - /* tp_call */ 0, - /* tp_str */ 0, - /* tp_getattro */ 0, - /* tp_setattro */ 0, - /* tp_as_buffer */ 0, - /* tp_flags */ Py_TPFLAGS_DEFAULT, - /* tp_doc */ _overlapped_Overlapped__doc__, - /* tp_traverse */ (traverseproc)Overlapped_traverse, - /* tp_clear */ 0, - /* tp_richcompare */ 0, - /* tp_weaklistoffset */ 0, - /* tp_iter */ 0, - /* tp_iternext */ 0, - /* tp_methods */ Overlapped_methods, - /* tp_members */ Overlapped_members, - /* tp_getset */ Overlapped_getsets, - /* tp_base */ 0, - /* tp_dict */ 0, - /* tp_descr_get */ 0, - /* tp_descr_set */ 0, - /* tp_dictoffset */ 0, - /* tp_init */ 0, - /* tp_alloc */ 0, - /* tp_new */ _overlapped_Overlapped, +static PyType_Slot overlapped_type_slots[] = { + {Py_tp_dealloc, Overlapped_dealloc}, + {Py_tp_doc, (char *)_overlapped_Overlapped__doc__}, + {Py_tp_traverse, Overlapped_traverse}, + {Py_tp_methods, Overlapped_methods}, + {Py_tp_members, Overlapped_members}, + {Py_tp_getset, Overlapped_getsets}, + {Py_tp_new, _overlapped_Overlapped}, + {0,0} +}; + +static PyType_Spec overlapped_type_spec = { + .name = "_overlapped.Overlapped", + .basicsize = sizeof(OverlappedObject), + .flags = Py_TPFLAGS_DEFAULT, + .slots = overlapped_type_slots }; static PyMethodDef overlapped_functions[] = { @@ -1904,41 +1897,67 @@ static PyMethodDef overlapped_functions[] = { {NULL} }; -static struct PyModuleDef overlapped_module = { - PyModuleDef_HEAD_INIT, - "_overlapped", - NULL, - -1, - overlapped_functions, - NULL, - NULL, - NULL, - NULL -}; +static int +overlapped_traverse(PyObject *module, visitproc visit, void *arg) +{ + OverlappedState *state = overlapped_get_state(module); + Py_VISIT(state->overlapped_type); + return 0; +} -#define WINAPI_CONSTANT(fmt, con) \ - PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con)) +static int +overlapped_clear(PyObject *module) +{ + OverlappedState *state = overlapped_get_state(module); + Py_CLEAR(state->overlapped_type); + return 0; +} -PyMODINIT_FUNC -PyInit__overlapped(void) +static void +overlapped_free(void *module) { - PyObject *m, *d; + overlapped_clear((PyObject *)module); +} +#define WINAPI_CONSTANT(fmt, con) \ + do { \ + PyObject *value = Py_BuildValue(fmt, con); \ + if (value == NULL) { \ + return -1; \ + } \ + if (PyDict_SetItemString(d, #con, value) < 0) { \ + Py_DECREF(value); \ + return -1; \ + } \ + Py_DECREF(value); \ + } while (0) + +static int +overlapped_exec(PyObject *module) +{ /* Ensure WSAStartup() called before initializing function pointers */ - m = PyImport_ImportModule("_socket"); - if (!m) - return NULL; + PyObject *m = PyImport_ImportModule("_socket"); + if (!m) { + return -1; + } + Py_DECREF(m); if (initialize_function_pointers() < 0) - return NULL; + return -1; - m = PyModule_Create(&overlapped_module); - if (PyModule_AddType(m, &OverlappedType) < 0) { - return NULL; + OverlappedState *st = overlapped_get_state(module); + st->overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec( + m, &overlapped_type_spec, NULL); + if (st->overlapped_type == NULL) { + return -1; } - d = PyModule_GetDict(m); + if (PyModule_AddType(module, st->overlapped_type) < 0) { + return -1; + } + + PyObject *d = PyModule_GetDict(module); WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING); WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED); @@ -1952,5 +1971,27 @@ PyInit__overlapped(void) WINAPI_CONSTANT(F_DWORD, SO_UPDATE_CONNECT_CONTEXT); WINAPI_CONSTANT(F_DWORD, TF_REUSE_SOCKET); - return m; + return 0; +} + +static PyModuleDef_Slot overlapped_slots[] = { + {Py_mod_exec, overlapped_exec}, + {0, NULL} +}; + +static struct PyModuleDef overlapped_module = { + PyModuleDef_HEAD_INIT, + .m_name = "_overlapped", + .m_size = sizeof(OverlappedState), + .m_methods = overlapped_functions, + .m_slots = overlapped_slots, + .m_traverse = overlapped_traverse, + .m_clear = overlapped_clear, + .m_free = overlapped_free +}; + +PyMODINIT_FUNC +PyInit__overlapped(void) +{ + return PyModuleDef_Init(&overlapped_module); } From 3da51022ae24c774f044c7d7281000ec570ad099 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Tue, 1 Sep 2020 17:23:32 -0500 Subject: [PATCH 2/4] blurb --- .../2020-09-01-17-22-35.bpo-1635741.CnRME3.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-22-35.bpo-1635741.CnRME3.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-22-35.bpo-1635741.CnRME3.rst b/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-22-35.bpo-1635741.CnRME3.rst new file mode 100644 index 00000000000000..b5f48da77540cd --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-22-35.bpo-1635741.CnRME3.rst @@ -0,0 +1,2 @@ +Port the :mod:`overlapped` extension module to multi-phase initialization +(:pep:`489`). From cb97040334e1c7b87bf6ed74fb722f8bfa82d641 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Fri, 4 Sep 2020 20:23:14 -0500 Subject: [PATCH 3/4] don'tuse PyModule_GetDict --- Modules/overlapped.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Modules/overlapped.c b/Modules/overlapped.c index a769da86dc624a..6aa1142c07294f 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -1925,30 +1925,29 @@ overlapped_free(void *module) if (value == NULL) { \ return -1; \ } \ - if (PyDict_SetItemString(d, #con, value) < 0) { \ + if (PyModule_AddObject(module, #con, value) < 0 ) { \ Py_DECREF(value); \ return -1; \ } \ - Py_DECREF(value); \ } while (0) static int overlapped_exec(PyObject *module) { /* Ensure WSAStartup() called before initializing function pointers */ - PyObject *m = PyImport_ImportModule("_socket"); - if (!m) { + PyObject *socket_module = PyImport_ImportModule("_socket"); + if (!socket_module) { return -1; } - Py_DECREF(m); + Py_DECREF(socket_module); if (initialize_function_pointers() < 0) return -1; OverlappedState *st = overlapped_get_state(module); st->overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec( - m, &overlapped_type_spec, NULL); + module, &overlapped_type_spec, NULL); if (st->overlapped_type == NULL) { return -1; } @@ -1957,8 +1956,6 @@ overlapped_exec(PyObject *module) return -1; } - PyObject *d = PyModule_GetDict(module); - WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING); WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED); WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED); From b00a02d77abb9ef58ad4b65a564300e3bbd31c00 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 7 Sep 2020 07:36:16 -0500 Subject: [PATCH 4/4] minor change --- .../2020-09-01-17-22-35.bpo-1635741.CnRME3.rst | 2 +- Modules/overlapped.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-22-35.bpo-1635741.CnRME3.rst b/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-22-35.bpo-1635741.CnRME3.rst index b5f48da77540cd..76f985bb87b4e9 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-22-35.bpo-1635741.CnRME3.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-22-35.bpo-1635741.CnRME3.rst @@ -1,2 +1,2 @@ -Port the :mod:`overlapped` extension module to multi-phase initialization +Port the :mod:`_overlapped` extension module to multi-phase initialization (:pep:`489`). diff --git a/Modules/overlapped.c b/Modules/overlapped.c index 6aa1142c07294f..3829932070a961 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -1942,8 +1942,9 @@ overlapped_exec(PyObject *module) Py_DECREF(socket_module); - if (initialize_function_pointers() < 0) + if (initialize_function_pointers() < 0) { return -1; + } OverlappedState *st = overlapped_get_state(module); st->overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec(