Skip to content

Commit f22b7ca

Browse files
author
Erlend Egeberg Aasland
authored
bpo-41798: Allocate _socket module C API on the heap (GH-24126)
1 parent ff8458b commit f22b7ca

File tree

2 files changed

+47
-16
lines changed

2 files changed

+47
-16
lines changed

Modules/socketmodule.c

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7033,16 +7033,36 @@ os_init(void)
70337033
}
70347034
#endif
70357035

7036+
static void
7037+
sock_free_api(PySocketModule_APIObject *capi)
7038+
{
7039+
Py_DECREF(capi->Sock_Type);
7040+
Py_DECREF(capi->error);
7041+
Py_DECREF(capi->timeout_error);
7042+
PyMem_Free(capi);
7043+
}
70367044

7037-
/* C API table - always add new things to the end for binary
7038-
compatibility. */
7039-
static
7040-
PySocketModule_APIObject PySocketModuleAPI =
7045+
static void
7046+
sock_destroy_api(PyObject *capsule)
70417047
{
7042-
&sock_type,
7043-
NULL,
7044-
NULL
7045-
};
7048+
void *capi = PyCapsule_GetPointer(capsule, PySocket_CAPSULE_NAME);
7049+
sock_free_api(capi);
7050+
}
7051+
7052+
static PySocketModule_APIObject *
7053+
sock_get_api(void)
7054+
{
7055+
PySocketModule_APIObject *capi = PyMem_Malloc(sizeof(PySocketModule_APIObject));
7056+
if (capi == NULL) {
7057+
PyErr_NoMemory();
7058+
return NULL;
7059+
}
7060+
7061+
capi->Sock_Type = (PyTypeObject *)Py_NewRef(&sock_type);
7062+
capi->error = Py_NewRef(PyExc_OSError);
7063+
capi->timeout_error = Py_NewRef(PyExc_TimeoutError);
7064+
return capi;
7065+
}
70467066

70477067

70487068
/* Initialize the _socket module.
@@ -7091,8 +7111,6 @@ PyInit__socket(void)
70917111
if (m == NULL)
70927112
return NULL;
70937113

7094-
Py_INCREF(PyExc_OSError);
7095-
PySocketModuleAPI.error = PyExc_OSError;
70967114
Py_INCREF(PyExc_OSError);
70977115
PyModule_AddObject(m, "error", PyExc_OSError);
70987116
socket_herror = PyErr_NewException("socket.herror",
@@ -7107,8 +7125,6 @@ PyInit__socket(void)
71077125
return NULL;
71087126
Py_INCREF(socket_gaierror);
71097127
PyModule_AddObject(m, "gaierror", socket_gaierror);
7110-
7111-
PySocketModuleAPI.timeout_error = PyExc_TimeoutError;
71127128
PyModule_AddObjectRef(m, "timeout", PyExc_TimeoutError);
71137129

71147130
Py_INCREF((PyObject *)&sock_type);
@@ -7129,10 +7145,24 @@ PyInit__socket(void)
71297145
PyModule_AddObject(m, "has_ipv6", has_ipv6);
71307146

71317147
/* Export C API */
7132-
if (PyModule_AddObject(m, PySocket_CAPI_NAME,
7133-
PyCapsule_New(&PySocketModuleAPI, PySocket_CAPSULE_NAME, NULL)
7134-
) != 0)
7148+
PySocketModule_APIObject *capi = sock_get_api();
7149+
if (capi == NULL) {
7150+
Py_DECREF(m);
7151+
return NULL;
7152+
}
7153+
PyObject *capsule = PyCapsule_New(capi,
7154+
PySocket_CAPSULE_NAME,
7155+
sock_destroy_api);
7156+
if (capsule == NULL) {
7157+
sock_free_api(capi);
7158+
Py_DECREF(m);
7159+
return NULL;
7160+
}
7161+
if (PyModule_AddObject(m, PySocket_CAPI_NAME, capsule) < 0) {
7162+
Py_DECREF(capsule);
7163+
Py_DECREF(m);
71357164
return NULL;
7165+
}
71367166

71377167
/* Address families (we only support AF_INET and AF_UNIX) */
71387168
#ifdef AF_UNSPEC

Modules/socketmodule.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,8 @@ typedef struct {
342342
343343
*/
344344

345-
/* C API for usage by other Python modules */
345+
/* C API for usage by other Python modules.
346+
* Always add new things to the end for binary compatibility. */
346347
typedef struct {
347348
PyTypeObject *Sock_Type;
348349
PyObject *error;

0 commit comments

Comments
 (0)