Skip to content

Commit

Permalink
bpo-41798: Allocate _socket module C API on the heap (GH-24126)
Browse files Browse the repository at this point in the history
  • Loading branch information
Erlend Egeberg Aasland authored and adorilson committed Mar 11, 2021
1 parent ef62a7f commit 4f45939
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 16 deletions.
60 changes: 45 additions & 15 deletions Modules/socketmodule.c
Expand Up @@ -7033,16 +7033,36 @@ os_init(void)
}
#endif

static void
sock_free_api(PySocketModule_APIObject *capi)
{
Py_DECREF(capi->Sock_Type);
Py_DECREF(capi->error);
Py_DECREF(capi->timeout_error);
PyMem_Free(capi);
}

/* C API table - always add new things to the end for binary
compatibility. */
static
PySocketModule_APIObject PySocketModuleAPI =
static void
sock_destroy_api(PyObject *capsule)
{
&sock_type,
NULL,
NULL
};
void *capi = PyCapsule_GetPointer(capsule, PySocket_CAPSULE_NAME);
sock_free_api(capi);
}

static PySocketModule_APIObject *
sock_get_api(void)
{
PySocketModule_APIObject *capi = PyMem_Malloc(sizeof(PySocketModule_APIObject));
if (capi == NULL) {
PyErr_NoMemory();
return NULL;
}

capi->Sock_Type = (PyTypeObject *)Py_NewRef(&sock_type);
capi->error = Py_NewRef(PyExc_OSError);
capi->timeout_error = Py_NewRef(PyExc_TimeoutError);
return capi;
}


/* Initialize the _socket module.
Expand Down Expand Up @@ -7091,8 +7111,6 @@ PyInit__socket(void)
if (m == NULL)
return NULL;

Py_INCREF(PyExc_OSError);
PySocketModuleAPI.error = PyExc_OSError;
Py_INCREF(PyExc_OSError);
PyModule_AddObject(m, "error", PyExc_OSError);
socket_herror = PyErr_NewException("socket.herror",
Expand All @@ -7107,8 +7125,6 @@ PyInit__socket(void)
return NULL;
Py_INCREF(socket_gaierror);
PyModule_AddObject(m, "gaierror", socket_gaierror);

PySocketModuleAPI.timeout_error = PyExc_TimeoutError;
PyModule_AddObjectRef(m, "timeout", PyExc_TimeoutError);

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

/* Export C API */
if (PyModule_AddObject(m, PySocket_CAPI_NAME,
PyCapsule_New(&PySocketModuleAPI, PySocket_CAPSULE_NAME, NULL)
) != 0)
PySocketModule_APIObject *capi = sock_get_api();
if (capi == NULL) {
Py_DECREF(m);
return NULL;
}
PyObject *capsule = PyCapsule_New(capi,
PySocket_CAPSULE_NAME,
sock_destroy_api);
if (capsule == NULL) {
sock_free_api(capi);
Py_DECREF(m);
return NULL;
}
if (PyModule_AddObject(m, PySocket_CAPI_NAME, capsule) < 0) {
Py_DECREF(capsule);
Py_DECREF(m);
return NULL;
}

/* Address families (we only support AF_INET and AF_UNIX) */
#ifdef AF_UNSPEC
Expand Down
3 changes: 2 additions & 1 deletion Modules/socketmodule.h
Expand Up @@ -342,7 +342,8 @@ typedef struct {
*/

/* C API for usage by other Python modules */
/* C API for usage by other Python modules.
* Always add new things to the end for binary compatibility. */
typedef struct {
PyTypeObject *Sock_Type;
PyObject *error;
Expand Down

0 comments on commit 4f45939

Please sign in to comment.