Skip to content

bpo-41798: Allocate the datetime.datetime_CAPI on the heap memory. #24096

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 6, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 43 additions & 21 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -6473,26 +6473,44 @@ static PyMethodDef module_methods[] = {
{NULL, NULL}
};

/* C API. Clients get at this via PyDateTime_IMPORT, defined in
* datetime.h.
/* Get a new C API by calling this function.
* Clients get at C API via PyDateTime_IMPORT, defined in datetime.h.
*/
static PyDateTime_CAPI CAPI = {
&PyDateTime_DateType,
&PyDateTime_DateTimeType,
&PyDateTime_TimeType,
&PyDateTime_DeltaType,
&PyDateTime_TZInfoType,
NULL, // PyDatetime_TimeZone_UTC not initialized yet
new_date_ex,
new_datetime_ex,
new_time_ex,
new_delta_ex,
new_timezone,
datetime_fromtimestamp,
datetime_date_fromtimestamp_capi,
new_datetime_ex2,
new_time_ex2
};
static inline PyDateTime_CAPI *
get_datetime_capi(void)
{
PyDateTime_CAPI *capi = PyMem_Malloc(sizeof(PyDateTime_CAPI));
if (capi == NULL) {
PyErr_NoMemory();
return NULL;
}
capi->DateType = &PyDateTime_DateType;
capi->DateTimeType = &PyDateTime_DateTimeType;
capi->TimeType = &PyDateTime_TimeType;
capi->DeltaType = &PyDateTime_DeltaType;
capi->TZInfoType = &PyDateTime_TZInfoType;
capi->Date_FromDate = new_date_ex;
capi->DateTime_FromDateAndTime = new_datetime_ex;
capi->Time_FromTime = new_time_ex;
capi->Delta_FromDelta = new_delta_ex;
capi->TimeZone_FromTimeZone = new_timezone;
capi->DateTime_FromTimestamp = datetime_fromtimestamp;
capi->Date_FromTimestamp = datetime_date_fromtimestamp_capi;
capi->DateTime_FromDateAndTimeAndFold = new_datetime_ex2;
capi->Time_FromTimeAndFold = new_time_ex2;
// Make sure this function is called after PyDateTime_TimeZone_UTC has
// been initialized.
assert(PyDateTime_TimeZone_UTC != NULL);
capi->TimeZone_UTC = PyDateTime_TimeZone_UTC; // borrowed ref
return capi;
}

static void
datetime_destructor(PyObject *op)
{
void *ptr = PyCapsule_GetPointer(op, PyDateTime_CAPSULE_NAME);
PyMem_Free(ptr);
}

static int
_datetime_exec(PyObject *module)
Expand Down Expand Up @@ -6581,7 +6599,6 @@ _datetime_exec(PyObject *module)
}

PyDateTime_TimeZone_UTC = x;
CAPI.TimeZone_UTC = PyDateTime_TimeZone_UTC;

/* bpo-37642: These attributes are rounded to the nearest minute for backwards
* compatibility, even though the constructor will accept a wider range of
Expand Down Expand Up @@ -6619,8 +6636,13 @@ _datetime_exec(PyObject *module)
return -1;
}

x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL);
PyDateTime_CAPI *capi = get_datetime_capi();
if (capi == NULL) {
return -1;
}
x = PyCapsule_New(capi, PyDateTime_CAPSULE_NAME, datetime_destructor);
if (x == NULL) {
PyMem_Free(capi);
return -1;
}

Expand Down