bpo-42333: Port _ssl extension to multiphase initialization (PEP 489) (GH-23253)

- Introduce sslmodule_slots
- Introduce sslmodulestate
- Use sslmodulestate
- Get rid of PyState_FindModule
- Move new structs and helpers to header file
- Use macros to access state
- Keep a strong ref to socket type
This commit is contained in:
Christian Heimes 2021-04-17 20:06:38 +02:00 committed by GitHub
parent 76beadb8ff
commit 7f1305ef9e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 468 additions and 366 deletions

View file

@ -0,0 +1 @@
Port ``_ssl`` extension module to multiphase initialization.

File diff suppressed because it is too large Load diff

45
Modules/_ssl.h Normal file
View file

@ -0,0 +1,45 @@
#ifndef Py_SSL_H
#define Py_SSL_H
/*
* ssl module state
*/
typedef struct {
/* Types */
PyTypeObject *PySSLContext_Type;
PyTypeObject *PySSLSocket_Type;
PyTypeObject *PySSLMemoryBIO_Type;
PyTypeObject *PySSLSession_Type;
/* SSL error object */
PyObject *PySSLErrorObject;
PyObject *PySSLCertVerificationErrorObject;
PyObject *PySSLZeroReturnErrorObject;
PyObject *PySSLWantReadErrorObject;
PyObject *PySSLWantWriteErrorObject;
PyObject *PySSLSyscallErrorObject;
PyObject *PySSLEOFErrorObject;
/* Error mappings */
PyObject *err_codes_to_names;
PyObject *err_names_to_codes;
PyObject *lib_codes_to_names;
/* socket type from module CAPI */
PyTypeObject *Sock_Type;
} _sslmodulestate;
static struct PyModuleDef _sslmodule_def;
Py_LOCAL_INLINE(_sslmodulestate*)
get_ssl_state(PyObject *module)
{
void *state = PyModule_GetState(module);
assert(state != NULL);
return (_sslmodulestate *)state;
}
#define get_state_type(type) \
(get_ssl_state(_PyType_GetModuleByDef(type, &_sslmodule_def)))
#define get_state_ctx(c) (((PySSLContext *)(c))->state)
#define get_state_sock(s) (((PySSLSocket *)(s))->ctx->state)
#define get_state_mbio(b) ((_sslmodulestate *)PyType_GetModuleState(Py_TYPE(b)))
#endif /* Py_SSL_H */

View file

@ -21,7 +21,7 @@ _PySSL_msg_callback(int write_p, int version, int content_type,
threadstate = PyGILState_Ensure();
ssl_obj = (PySSLSocket *)SSL_get_app_data(ssl);
assert(PySSLSocket_Check(ssl_obj));
assert(Py_IS_TYPE(ssl_obj, get_state_sock(ssl_obj)->PySSLSocket_Type));
if (ssl_obj->ctx->msg_cb == NULL) {
PyGILState_Release(threadstate);
return;
@ -125,7 +125,7 @@ _PySSL_keylog_callback(const SSL *ssl, const char *line)
threadstate = PyGILState_Ensure();
ssl_obj = (PySSLSocket *)SSL_get_app_data(ssl);
assert(PySSLSocket_Check(ssl_obj));
assert(Py_IS_TYPE(ssl_obj, get_state_sock(ssl_obj)->PySSLSocket_Type));
if (ssl_obj->ctx->keylog_bio == NULL) {
return;
}
@ -199,7 +199,7 @@ _PySSLContext_set_keylog_filename(PySSLContext *self, PyObject *arg, void *c) {
self->keylog_bio = BIO_new_fp(fp, BIO_CLOSE | BIO_FP_TEXT);
if (self->keylog_bio == NULL) {
PyErr_SetString(PySSLErrorObject,
PyErr_SetString(get_state_ctx(self)->PySSLErrorObject,
"Can't malloc memory for keylog file");
return -1;
}

View file

@ -374,7 +374,7 @@ _ssl__SSLContext(PyTypeObject *type, PyObject *args, PyObject *kwargs)
PyObject *return_value = NULL;
int proto_version;
if ((type == PySSLContext_Type) &&
if ((type == get_state_type(type)->PySSLContext_Type) &&
!_PyArg_NoKeywords("_SSLContext", kwargs)) {
goto exit;
}
@ -619,8 +619,8 @@ _ssl__SSLContext__wrap_socket(PySSLContext *self, PyObject *const *args, Py_ssiz
if (!args) {
goto exit;
}
if (!PyObject_TypeCheck(args[0], PySocketModule.Sock_Type)) {
_PyArg_BadArgument("_wrap_socket", "argument 'sock'", (PySocketModule.Sock_Type)->tp_name, args[0]);
if (!PyObject_TypeCheck(args[0], get_state_ctx(self)->Sock_Type)) {
_PyArg_BadArgument("_wrap_socket", "argument 'sock'", (get_state_ctx(self)->Sock_Type)->tp_name, args[0]);
goto exit;
}
sock = args[0];
@ -689,13 +689,13 @@ _ssl__SSLContext__wrap_bio(PySSLContext *self, PyObject *const *args, Py_ssize_t
if (!args) {
goto exit;
}
if (!PyObject_TypeCheck(args[0], PySSLMemoryBIO_Type)) {
_PyArg_BadArgument("_wrap_bio", "argument 'incoming'", (PySSLMemoryBIO_Type)->tp_name, args[0]);
if (!PyObject_TypeCheck(args[0], get_state_ctx(self)->PySSLMemoryBIO_Type)) {
_PyArg_BadArgument("_wrap_bio", "argument 'incoming'", (get_state_ctx(self)->PySSLMemoryBIO_Type)->tp_name, args[0]);
goto exit;
}
incoming = (PySSLMemoryBIO *)args[0];
if (!PyObject_TypeCheck(args[1], PySSLMemoryBIO_Type)) {
_PyArg_BadArgument("_wrap_bio", "argument 'outgoing'", (PySSLMemoryBIO_Type)->tp_name, args[1]);
if (!PyObject_TypeCheck(args[1], get_state_ctx(self)->PySSLMemoryBIO_Type)) {
_PyArg_BadArgument("_wrap_bio", "argument 'outgoing'", (get_state_ctx(self)->PySSLMemoryBIO_Type)->tp_name, args[1]);
goto exit;
}
outgoing = (PySSLMemoryBIO *)args[1];
@ -850,11 +850,11 @@ _ssl_MemoryBIO(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
if ((type == PySSLMemoryBIO_Type) &&
if ((type == get_state_type(type)->PySSLMemoryBIO_Type) &&
!_PyArg_NoPositional("MemoryBIO", args)) {
goto exit;
}
if ((type == PySSLMemoryBIO_Type) &&
if ((type == get_state_type(type)->PySSLMemoryBIO_Type) &&
!_PyArg_NoKeywords("MemoryBIO", kwargs)) {
goto exit;
}
@ -1324,4 +1324,4 @@ exit:
#ifndef _SSL_ENUM_CRLS_METHODDEF
#define _SSL_ENUM_CRLS_METHODDEF
#endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */
/*[clinic end generated code: output=ae3d1851daba6562 input=a9049054013a1b77]*/
/*[clinic end generated code: output=83e68c77bd96789a input=a9049054013a1b77]*/

View file

@ -2428,14 +2428,6 @@ def split_var(name, sep):
self.missing.extend(['_ssl', '_hashlib'])
return None, None
self.add(Extension(
'_ssl', ['_ssl.c'],
include_dirs=openssl_includes,
library_dirs=openssl_libdirs,
libraries=openssl_libs,
depends=['socketmodule.h', '_ssl/debughelpers.c'])
)
if openssl_rpath == 'auto':
runtime_library_dirs = openssl_libdirs[:]
elif not openssl_rpath:
@ -2469,7 +2461,7 @@ def split_var(name, sep):
Extension(
'_ssl',
['_ssl.c'],
depends=['socketmodule.h', '_ssl/debughelpers.c'],
depends=['socketmodule.h', '_ssl/debughelpers.c', '_ssl.h'],
**openssl_extension_kwargs
)
)